56 Commits

Author SHA1 Message Date
280dd1a809 Merge pull request #208 from juliandescottes/feature-export-to-file
Feature export to file
2014-07-15 00:33:36 +02:00
c1900a07f0 Final fixes before new version 2014-07-15 00:31:24 +02:00
a43b20e182 fix lighten bug when starting on transparent pixel 2014-07-14 16:44:36 +02:00
b556143b66 fixed fps when restoring backup 2014-07-14 14:39:21 +02:00
19c99d1aa7 Fixed canvas ordering, fixed FPS during local import 2014-07-14 14:14:28 +02:00
dc78c3cecd Yet another history bug ! 2014-07-14 00:37:17 +02:00
829bcb8ad1 Simplified lighten + fixed frame caching bug 2014-07-13 21:01:50 +02:00
56f008bda6 restored history snapshot interval to 50 2014-07-13 18:17:13 +02:00
5350255eee fixed lighten reset + fixed history bug 2014-07-13 17:59:53 +02:00
d4884a2de5 Capture events on tmp download link created by FileUtils 2014-07-13 15:54:13 +02:00
581bd46dcd Cleanup + updated tooltips 2014-07-13 15:15:45 +02:00
1e8315f32c Switch back to imgstore-a 2014-07-13 14:11:49 +02:00
cc8460cc26 Fix gif worker URL on IE11 appengine mode 2014-07-13 14:02:35 +02:00
aa375315a2 Fixed mime type bug on Firefox 2014-07-13 01:01:33 +02:00
e5cb0717e2 cleanup 2014-07-13 00:43:35 +02:00
6af04bb599 cleanup 2014-07-13 00:21:36 +02:00
dfc3bfd181 Fixed Gruntfile for ghpages export 2014-07-12 21:14:07 +02:00
ad3dd935e0 Create 2 new dialog controllers
Image import is now triggering a popup after selecting the file.
Same for local saves.

Drag and drop of .piskel files opens the piskel immediately !

Remains to do :
- redesign the dialog for import image and browse local
- create dialog for recover session
- improve recover session to handle more than the last session
2014-07-12 15:34:50 +02:00
18ff6f88a7 Merge branch 'feature-dnd-images' into feature-export-to-file 2014-07-12 11:12:18 +02:00
b2fbe269d3 Merge branch 'master' into feature-export-to-file 2014-07-12 00:46:27 +02:00
a8ce829e6c Image dnd first implementation 2014-07-12 00:41:39 +02:00
2fabf68282 Merge pull request #203 from juliandescottes/feature-swap-color
Feature swap color
2014-07-11 00:25:22 +02:00
b66d5ee93b Cleanup of tooltip generation 2014-07-11 00:14:21 +02:00
982a5ab048 Refactoring tooltip code + display CMD on mac 2014-07-10 01:32:16 +02:00
a6d70920e2 Improve tooltip design 2014-07-09 07:56:22 +02:00
b311312260 Removed hack from ColorPicker class 2014-07-08 20:09:21 +02:00
665d2bd9bc Settled on temp icon for swap colors 2014-07-08 20:06:03 +02:00
4aac65fb9e Settled on temp icon for swap colors 2014-07-08 20:04:16 +02:00
4102e929f4 Removed unused methods from Frame 2014-07-07 23:33:29 +02:00
b3bb2472f1 perf step 1 : ok on chrome,horrible on FF 2014-07-07 22:48:13 +02:00
a6d939cc9a Fix selection paste transparent pixels 2014-07-06 23:59:07 +02:00
304a5c06da swap color : initial implementation 2014-07-06 23:56:50 +02:00
707a69182f Fixed IE issues + verisoning for iframeloader and boot 2014-07-06 17:15:18 +02:00
8f5ead43d9 Fix : remove cache issues for css, js, templates
Packaged css and js are now suffixed with the build date.
All templates are exported to a folder named after the build date.
Streamlined the build process to copy files to piskel-website.

Isolated common part between piskel and piskel-website in a separated
template, which is now completely created by the grunt build of piskel.

Added a windows CMD script to copy the static resources to piskel-website.
2014-07-06 16:17:14 +02:00
41a4ee3f3d cleanup of import tab 2014-07-06 12:55:29 +02:00
f8b6d7b0d3 Merge branch 'master' into feature-export-to-file 2014-07-05 23:53:03 +02:00
84e757768e Merge pull request #200 from juliandescottes/enhancement-horizontal-mirror
Enhancement : modifiers for Mirror pen
2014-07-05 23:11:20 +02:00
264e236473 Merge pull request #199 from juliandescottes/enhancement-overlay-shortcut
Enhancement overlay shortcut
2014-07-05 23:10:55 +02:00
96fc5f2418 Enhancement : modifiers for Mirror pen 2014-07-05 17:04:18 +02:00
26a463c4b4 Updated font-icon with a better grid 2014-07-05 14:16:53 +02:00
8e425c64d4 Add fonts to copy task 2014-07-05 11:45:10 +02:00
bf9be5de2d Fixed input range style on IE11 2014-07-05 11:41:40 +02:00
2c235e659b Fixed layout on FF, removed options in drawer 2014-07-05 11:39:02 +02:00
a77168986a Enhancement : Shortcuts for onion kin + layer prev
Added 2 new icons :
- Animated Preview Panel : toggle onion skin
- Layers Toolbox : toggle layer preview

Added an icon font generated with icomoon.

SVGs for both icons have been made under Inkscape and are kept under
misc/svg.

All reference SVGs have been moved to misc/svg.

Added 2 keyboard shortcuts for toggling onion skin / layer preview :
- alt L : toggle layer preview
- alt O : toggle onion skin
2014-07-05 11:27:11 +02:00
24186d5aec Added keyboard shortcuts 2014-07-04 19:17:02 +02:00
7b3f5ee858 Merged changes 2014-07-03 23:40:30 +02:00
939042a645 Merge pull request #195 from juliandescottes/performance-animated-preview
Performance animated preview
2014-07-03 23:29:01 +02:00
fa4e96e7e5 Added documentation in CachedFrameProcessor 2014-07-03 23:23:31 +02:00
fa626532ba cleanup of performance improvement 2014-07-03 00:48:49 +02:00
a2e2459169 cleanup of performance improvement 2014-07-03 00:09:47 +02:00
8a70943b09 Fix : fix classes extending simplePen 2014-07-02 07:34:07 +02:00
d126023c4a temp 2014-06-30 20:38:14 +02:00
f2281d7125 temp commit 2014-06-29 23:16:37 +02:00
3efa94dce5 Merge branch 'master' into feature-export-to-file 2014-06-27 07:16:48 +02:00
bd7ebc5f7d Fix : add backup service and make undo safer 2014-06-27 02:08:00 +02:00
89466d582a Feature : Save Piskel project as File
First commit :
Removed Local storage feature
Added 'download project' 'open project' options

First attempt at simplifying right panel.

To be continued ...
2014-06-23 00:49:54 +02:00
122 changed files with 2829 additions and 1031 deletions

1
.gitignore vendored
View File

@ -18,6 +18,7 @@ diff.txt
# build destination
dest
build/closure/closure_compiled_binary.js
# marked as private
*.private.*

View File

@ -13,6 +13,10 @@
var SOURCE_FOLDER = "src";
module.exports = function(grunt) {
var dateFormat = require('dateformat');
var now = new Date();
var version = '-' + dateFormat(now, "yyyy-mm-dd-hh-MM");
var mapToSrcFolder = function (path) {return [SOURCE_FOLDER, path].join('/');};
var piskelScripts = require('./src/piskel-script-list.js').scripts.map(mapToSrcFolder);
@ -110,11 +114,11 @@ module.exports = function(grunt) {
separator : ';'
},
src : piskelScripts,
dest : 'dest/js/piskel-packaged.js'
dest : 'dest/js/piskel-packaged' + version + '.js'
},
css : {
src : piskelStyles,
dest : 'dest/css/piskel-style-packaged.css'
dest : 'dest/css/piskel-style-packaged' + version + '.css'
}
},
uglify : {
@ -123,17 +127,59 @@ module.exports = function(grunt) {
},
my_target : {
files : {
'dest/js/piskel-packaged-min.js' : ['dest/js/piskel-packaged.js']
'dest/js/piskel-packaged-min.js' : ['dest/js/piskel-packaged' + version + '.js']
}
}
},
replace: {
main: {
options: {
patterns: [
{
match: 'version',
replacement: version
}
]
},
files: [
{expand: true, flatten: true, src: ['src/piskel-boot-0.1.0.js'], dest: 'dest/'}
]
},
editor: {
options: {
patterns: [
{
match: /templates\//g,
replacement: "../templates"+version+"/"
},{
match: /^(.|[\r\n])*<!--body-main-start-->/,
replacement: "",
description : "Remove everything before body-main-start comment"
},{
match: /<!--body-main-end-->(.|[\r\n])*$/,
replacement: "",
description : "Remove everything after body-main-end comment"
},{
match: /([\r\n]) /g,
replacement: "$1",
description : "Decrease indentation by one"
}
]
},
files: [
{src: ['src/index.html'], dest: 'dest/piskelapp-partials/main-partial.html'}
]
}
},
copy: {
main: {
files: [
{src: ['src/piskel-boot.js'], dest: 'dest/piskel-boot.js'},
{src: ['dest/js/piskel-packaged-min.js'], dest: 'dest/js/piskel-packaged-min' + version + '.js'},
{src: ['src/logo.png'], dest: 'dest/logo.png'},
{src: ['src/js/lib/iframeLoader.js'], dest: 'dest/js/lib/iframeLoader.js'},
{src: ['src/js/lib/iframeLoader-0.1.0.js'], dest: 'dest/js/lib/iframeLoader-0.1.0.js'},
{src: ['src/js/lib/gif/gif.ie.worker.js'], dest: 'dest/js/lib/gif/gif.ie.worker.js'},
{expand: true, src: ['img/**'], cwd: 'src/', dest: 'dest/', filter: 'isFile'},
{expand: true, src: ['css/fonts/**'], cwd: 'src/', dest: 'dest/', filter: 'isFile'},
{expand: true, src: ['**/*.html'], cwd: 'src/', dest: 'dest/', filter: 'isFile'}
]
}
@ -181,7 +227,7 @@ module.exports = function(grunt) {
},
src: [
'src/js/**/*.js',
'src/piskel-boot.js',
'src/piskel-boot-0.1.0.js',
'src/piskel-script-list.js',
'!src/js/lib/**/*.js'
],
@ -222,6 +268,7 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-express');
grunt.loadNpmTasks('grunt-replace');
grunt.loadNpmTasks('grunt-ghost');
grunt.loadNpmTasks('grunt-open');
grunt.loadNpmTasks('grunt-leading-indent');
@ -240,7 +287,9 @@ module.exports = function(grunt) {
// Compile JS code (eg verify JSDoc annotation and types, no actual minified code generated).
grunt.registerTask('compile', ['closureCompiler:compile', 'clean:after']);
grunt.registerTask('merge', ['concat:js', 'concat:css', 'uglify', 'copy']);
grunt.registerTask('rep', ['replace:main', 'replace:editor']);
grunt.registerTask('merge', ['concat:js', 'concat:css', 'uglify', 'rep', 'copy']);
// Validate & Build
grunt.registerTask('default', ['clean:before', 'lint', 'compile', 'merge']);

68
misc/icons/SVG/eye.svg Normal file
View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="300"
height="140.00085"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="eye.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="-6.0052729"
inkscape:cy="93.159467"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1148"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-223.21875,-469.24915)">
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 373.21875,469.25 c -63.15236,-0.28299 -150,70 -150,70 0,0 78.75568,70 150,70 62.82091,0 150,-70 150,-70 0,0 -87.47199,-69.71981 -150,-70 z m -1.5,22.3125 c 27.44855,0 49.6875,22.23895 49.6875,49.6875 0,27.44855 -22.23895,49.6875 -49.6875,49.6875 C 344.2702,590.9375 322,568.69855 322,541.25 c 0,-27.44855 22.2702,-49.6875 49.71875,-49.6875 z m 0.0312,18.34375 c -17.85254,0 -32.34375,14.49121 -32.34375,32.34375 0,17.85254 14.49121,32.3125 32.34375,32.3125 17.85254,0 32.3125,-14.45996 32.3125,-32.3125 0,-17.85254 -14.45996,-32.34375 -32.3125,-32.34375 z"
id="path2987"
inkscape:export-filename="C:\Development\git\piskel\misc\icons\eye.png"
inkscape:export-xdpi="28.799999"
inkscape:export-ydpi="28.799999"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

99
misc/icons/SVG/onion.svg Normal file
View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="484.83377"
height="430.80322"
id="svg3775"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="New document 3">
<defs
id="defs3777" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.04375"
inkscape:cx="-429.81362"
inkscape:cy="-202.97901"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1148"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<metadata
id="metadata3780">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-108.38875,-334.08796)">
<g
id="g4409">
<g
id="g4402" />
<g
transform="translate(0,0.82903262)"
id="g4395">
<path
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:25;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
d="m 395.27679,333.25893 -27.75,24.625 -1.65625,-9 -15.87054,4.59375 0,30.6875 1.02679,21.75 16.5625,-14.6875 13.6875,-12.15625 c -0.38933,5.52995 -0.57204,11.36571 -0.1875,17.84375 0.60884,10.25666 3.42535,19.47486 9.03125,26.6875 5.6059,7.21264 13.15778,11.83264 21.53125,15.65625 16.74693,7.64722 37.6168,20.19024 63.19196,41.4465 48.42535,40.24771 54.41585,60.33492 63.14228,95.72811 8.30827,46.0064 -4.89609,79.1393 -23.94924,107.24539 -13.61329,20.08154 -30.46397,37.90172 -67.50554,45.41482 -37.04157,7.5131 -71.72672,9.9375 -96.53125,9.9375 l 0,25 c 26.40206,0 62.17269,-2.46078 101.5,-10.4375 39.32731,-7.97672 78.11592,-20.77325 101.8125,-45.5625 25.65093,-26.83371 50.16969,-75.46693 35.5,-151.5 l -0.0312,-0.125 -0.0312,-0.125 c -6.53497,-30.32511 -26.37349,-75.86993 -103.9375,-109.59375 -32.08342,-13.94946 -49.48883,-22.95257 -62.57589,-28.92857 -6.54353,-2.988 -10.31288,-6.85833 -12.36607,-9.5 -2.05319,-2.64167 -3.40095,-5.87935 -3.8125,-12.8125 -0.92607,-15.60085 1.34241,-27.46751 3.71875,-35.3125 2.37634,-7.84499 4.375,-10.875 4.375,-10.875 l -18.875,-16 z"
id="path3783-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccsssscssccsscccsssssccc" />
<path
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:25;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
d="m 368.02679,382.44643 c 0,0 -18.02679,-4.71234 -18.02679,1.3125 0,33.38646 -0.45698,39.28362 10.99554,62.875 11.45252,23.59138 26.22845,47.86253 48.53571,68.45982 42.18558,38.95183 38.76978,44.87254 45.77232,64.91071 2.57793,7.37689 3.66466,24.51253 1.875,37.96875 -1.78965,13.45623 -6.8081,31.21802 -13.40625,41.3125 -10.36811,15.86211 -18.71831,32.07642 -38.55357,43.09375 C 384.4983,713.88847 366.62548,716.375 350,716.375 l 0,25 c 20.82486,0 44.52967,-5.01706 69.5625,-15.125 25.03283,-10.10794 49.12742,-25.27054 63.71875,-47.59375 9.77369,-14.95272 20.06105,-37.72017 22.33202,-55.91561 2.27097,-18.19544 6.78209,-33.89274 -5.08281,-58.40387 -18.26325,-37.72918 -42.54947,-49.06002 -72.19845,-74.15863 -18.35479,-15.5378 -34.85805,-33.83125 -44.86772,-54.45046 -10.00967,-20.61921 -14.81706,-41.55822 -15.4375,-53.28125 z"
id="path3783-9-4-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csssszssccssssssc" />
<path
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:25;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
d="M 364.71429,398.50893 350,399.85268 c 0.74677,14.10988 0,43.14662 0,70.71875 0,13.09078 2.17726,28.99404 4.22321,39.97321 3.9423,21.15552 10.51352,34.8833 14.63393,48.16965 3.27485,10.5598 6.94665,25.34012 9.3884,31.02232 6.61244,15.3878 7.52886,34.1921 0.75446,55.84375 -6.86056,21.92704 -17.55684,42.94479 -35.42857,49.84375 L 350,716.625 c 25.86119,-9.9831 62.03992,-38.1333 71.93512,-69.75936 8.9188,-28.50537 3.28613,-54.26844 -4.84375,-73.1875 -4.92941,-11.47123 -9.61575,-19.37277 -14.86607,-28.9375 -6.46007,-11.76857 -20.1885,-26.52209 -24.11895,-38.53817 -3.57466,-10.92835 -7.82736,-24.14439 -8.92331,-37.66229 -2.1919,-27.03581 -3.63369,-54.77948 -4.46875,-70.03125 z"
id="path3783-9-4-4-8-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccsssssccsssssc" />
</g>
</g>
<path
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:25;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
d="m 306.33447,334.11887 27.75,24.625 1.65625,-9 15.87054,4.59375 0,30.6875 -1.02679,21.75 -16.5625,-14.6875 -13.6875,-12.15625 c 0.38933,5.52995 0.57204,11.36571 0.1875,17.84375 -0.60884,10.25666 0.61526,20.48501 -4.99064,27.69765 -5.6059,7.21264 -12.14763,16.88341 -20.5211,20.70702 -16.74693,7.64722 -36.60664,20.19024 -62.1818,41.4465 -48.42535,40.24771 -47.34479,51.24354 -56.07122,86.63673 -3.25751,47.01655 -5.92183,46.3581 4.75635,78.96112 6.45302,19.70261 22.38275,38.91187 59.42432,56.52649 34.13302,16.23151 85.86885,30.14056 110.67338,30.14056 l 0,25 c -26.40206,0 -62.17269,-2.46078 -101.5,-10.4375 -39.32731,-7.97672 -78.11592,-20.77325 -101.8125,-45.5625 -25.65093,-26.83371 -50.169693,-75.46693 -35.5,-151.5 l 0.0312,-0.125 0.0312,-0.125 c 6.53497,-30.32511 26.37349,-75.86993 103.9375,-109.59375 32.08342,-13.94946 49.48883,-22.95257 62.57589,-28.92857 6.54353,-2.988 10.31288,-6.85833 12.36607,-9.5 2.05319,-2.64167 3.40095,-5.87935 3.8125,-12.8125 0.92607,-15.60085 -1.34241,-27.46751 -3.71875,-35.3125 -2.37634,-7.84499 -4.375,-10.875 -4.375,-10.875 l 18.875,-16 z"
id="path3783-2-4"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccsssscssccsscccsssssccc" />
<path
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:25;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
d="m 343.97613,380.44701 9.00001,12.77232 c -0.74677,14.10988 0,43.14662 0,70.71875 0,13.09078 3.53703,30.42261 1.49108,41.40178 -3.9423,21.15552 -3.37067,28.45473 -7.49108,41.74108 -3.27485,10.5598 -6.94665,28.91155 -9.3884,34.59375 -6.61244,15.3878 -8.24315,50.62067 -1.46875,72.27232 6.86056,21.92704 11.12828,50.08764 21.85715,66.27232 l 3.98985,41.15013 C 338.24766,729.2435 314.3133,692.32754 304.4181,660.70148 c -8.9188,-28.50537 -8.28613,-78.55416 -0.15625,-97.47322 4.92941,-11.47123 9.61575,-22.9442 14.86607,-32.50893 6.46007,-11.76857 10.13774,-23.49163 13.05804,-36.51786 2.51528,-11.21964 6.93976,-29.49102 8.03571,-43.00892 2.1919,-27.03581 2.9194,-55.49377 3.75446,-70.74554 z"
id="path3783-9-4-4-8-8-7"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccsssssccsssssc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="435"
height="409.28125"
id="svg3768"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="New document 3">
<defs
id="defs3770" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="87.95854"
inkscape:cy="195.23297"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="1148"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata3773">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-151.0625,-197.71875)">
<rect
style="fill:none;stroke:#ffffff;stroke-width:35;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3784"
width="400"
height="374.28571"
x="168.57143"
y="215.21933" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 368.5625,209.5 0,97.0625 c -18.16488,0.20304 -36.33513,0.39071 -54.5,0.59375 l 0,-51.1875 c -36.22093,27.13868 -72.43533,54.2988 -108.65625,81.4375 l 107.375,91.46875 1.28125,-53.5 54.5,0.96875 0,62.25 c 20.86255,0.2332 41.73121,0.45431 62.59375,0.6875 l 0,-51.1875 C 467.37718,415.23243 503.59158,442.3613 539.8125,469.5 l -107.40625,91.5 -1.25,-53.5 -62.59375,1.09375 0,75.1875 200,0 0,-365.71875 -200,-8.5625 z"
id="path4296"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="305.0015"
height="340.10172"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
inkscape:export-filename="C:\Development\git\piskel\src\img\tools\swap.png"
inkscape:export-xdpi="28.799999"
inkscape:export-ydpi="28.799999"
sodipodi:docname="swap-colors.svg">
<defs
id="defs2994" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="8.3838947"
inkscape:cy="209.5365"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1148"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-253.81175,62.601668)">
<path
style="fill:none;stroke:#ffffff;stroke-width:25;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 281.31983,48.818994 c 3.33333,70.714286 6.66667,141.428566 10,212.142856 61.21871,3.33294 122.57845,5.69263 183.84823,2.1217 15.38711,-0.63513 30.77146,-1.33859 46.15177,-2.1217 3.33333,-70.71429 6.66667,-141.42857 10,-212.142856 -62.39939,12.482847 -126.73342,18.836303 -190.05871,9.668003 -20.08786,-2.492087 -40.09989,-5.6543 -59.94129,-9.668003 z"
id="path3907"
inkscape:connector-curvature="0"
inkscape:export-filename="C:\Development\git\piskel\src\img\tools\swap.png"
inkscape:export-xdpi="28.799999"
inkscape:export-ydpi="28.799999" />
<path
style="fill:none;stroke:#ffffff;stroke-width:15;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 261.31983,63.818994 c 0,-10 0,-20 0,-30 17.1189,-42.7715577 62.54009,-66.510405 106.22509,-72.841714 51.17865,-7.022275 108.04464,-2.652241 150.47229,29.6746917 14.38134,11.798678 28.46011,26.7242963 33.30262,44.9943353 0,9.390896 0,18.781791 0,28.172687"
id="path3909"
inkscape:connector-curvature="0"
inkscape:export-filename="C:\Development\git\piskel\src\img\tools\swap.png"
inkscape:export-xdpi="28.799999"
inkscape:export-ydpi="28.799999" />
<path
style="fill:none;stroke:#ffffff;stroke-width:35;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 364.53412,-41.538146 c 25.60486,-3.886191 51.66473,-4.881507 77.20839,0.0707 l 3.09159,0.466979 1.12859,0.176599"
id="path3915"
inkscape:connector-curvature="0"
inkscape:export-filename="C:\Development\git\piskel\src\img\tools\swap.png"
inkscape:export-xdpi="28.799999"
inkscape:export-ydpi="28.799999" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 154.55334,129.87795 0.68071,15.85947 c 0,0 -57.346456,21.06263 -57.436416,36.51009 -0.09,15.44746 36.662436,29.96772 55.746256,42.34379 19.08382,12.37606 46.83462,28.70031 47.51123,48.36912 C 200.90809,289.78491 152.86,310.7174 152.86,310.7174 l 0.68319,14.23203 111.11677,-2.02031 11.11168,-206.07112 z"
id="path3764"
inkscape:connector-curvature="0"
transform="translate(253.81175,-62.601668)"
sodipodi:nodetypes="cczzcccccc"
inkscape:export-filename="C:\Development\git\piskel\src\img\tools\swap.png"
inkscape:export-xdpi="28.799999"
inkscape:export-ydpi="28.799999" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,21 @@
@ECHO off
SETLOCAL
SET PISKEL_PATH="C:\Development\git\piskel"
SET PISKELAPP_PATH="C:\Development\git\piskel-website"
ECHO "Copying files to piskelapp"
XCOPY "%PISKEL_PATH%\dest" "%PISKELAPP_PATH%\static\editor" /e /i /h /y
ECHO "Delete previous partial"
DEL "%PISKELAPP_PATH%\templates\editor\main-partial.html"
ECHO "Copy new partial"
MOVE "%PISKELAPP_PATH%\static\editor\piskelapp-partials\main-partial.html" "%PISKELAPP_PATH%\templates\editor"
ECHO "Delete temp partial"
RMDIR "%PISKELAPP_PATH%\static\editor\piskelapp-partials\" /S /Q
PAUSE
explorer "%PISKELAPP_PATH%\"
ENDLOCAL

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="http://localhost:9901/?debug" />
<title>change-colors</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">change-colors</td></tr>
</thead><tbody>
<tr>
<td>open</td>
<td>/?debug</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>css=div.sp-preview-inner</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>css=input.sp-input</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>css=input.sp-input</td>
<td>rgb(170, 187, 204)</td>
</tr>
<tr>
<td>mouseDown</td>
<td>id=preview-list-scroller</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>css=div.swap-colors-icon</td>
<td></td>
</tr>
</tbody></table>
</body>
</html>

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="http://localhost:9901/?debug" />
<title>change-size</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">change-size</td></tr>
</thead><tbody>
<tr>
<td>open</td>
<td>/?debug</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>css=div.tool-icon.resize-icon</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>name=resize-width</td>
<td>64</td>
</tr>
<tr>
<td>type</td>
<td>name=resize-height</td>
<td>64</td>
</tr>
<tr>
<td>click</td>
<td>name=resize-content-checkbox</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//input[@value='Resize']</td>
<td></td>
</tr>
<tr>
<td>mouseDown</td>
<td>id=column-wrapper</td>
<td></td>
</tr>
</tbody></table>
</body>
</html>

View File

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="http://localhost:9901/?debug" />
<title>Select tools</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Select tools</td></tr>
</thead><tbody>
<tr>
<td>open</td>
<td>/?debug</td>
<td></td>
</tr>
<tr>
<td>mouseDown</td>
<td>//ul[@id='tools-container']/li[2]</td>
<td></td>
</tr>
<tr>
<td>mouseDown</td>
<td>//ul[@id='tools-container']/li[3]</td>
<td></td>
</tr>
<tr>
<td>mouseDown</td>
<td>//ul[@id='tools-container']/li[4]</td>
<td></td>
</tr>
<tr>
<td>mouseDown</td>
<td>//ul[@id='tools-container']/li[5]</td>
<td></td>
</tr>
<tr>
<td>mouseDown</td>
<td>//ul[@id='tools-container']/li[6]</td>
<td></td>
</tr>
<tr>
<td>mouseDown</td>
<td>//ul[@id='tools-container']/li[7]</td>
<td></td>
</tr>
<tr>
<td>mouseDown</td>
<td>//ul[@id='tools-container']/li[8]</td>
<td></td>
</tr>
<tr>
<td>mouseDown</td>
<td>//ul[@id='tools-container']/li[9]</td>
<td></td>
</tr>
<tr>
<td>mouseDown</td>
<td>//ul[@id='tools-container']/li[10]</td>
<td></td>
</tr>
<tr>
<td>mouseDown</td>
<td>//ul[@id='tools-container']/li[11]</td>
<td></td>
</tr>
<tr>
<td>mouseDown</td>
<td>//ul[@id='tools-container']/li[12]</td>
<td></td>
</tr>
<tr>
<td>mouseDown</td>
<td>//ul[@id='tools-container']/li[13]</td>
<td></td>
</tr>
</tbody></table>
</body>
</html>

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="http://localhost:9901/?debug" />
<title>user-preferences</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">user-preferences</td></tr>
</thead><tbody>
<tr>
<td>open</td>
<td>/?debug</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>css=div.tool-icon.gear-icon</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>css=div.background-picker.lowcont-medium-picker-background</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>css=div.background-picker.medium-picker-background</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>css=div.background-picker.light-picker-background</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>id=grid-width</td>
<td></td>
</tr>
<tr>
<td>select</td>
<td>id=grid-width</td>
<td>label=Enabled - 1px wide</td>
</tr>
<tr>
<td>click</td>
<td>css=option[value=&quot;1&quot;]</td>
<td></td>
</tr>
<tr>
<td>select</td>
<td>id=grid-width</td>
<td>label=Enabled - 2px wide</td>
</tr>
<tr>
<td>click</td>
<td>css=option[value=&quot;2&quot;]</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>id=grid-width</td>
<td></td>
</tr>
<tr>
<td>select</td>
<td>id=grid-width</td>
<td>label=Enabled - 3px wide</td>
</tr>
<tr>
<td>click</td>
<td>css=option[value=&quot;3&quot;]</td>
<td></td>
</tr>
<tr>
<td>select</td>
<td>id=grid-width</td>
<td>label=Enabled - 4px wide</td>
</tr>
<tr>
<td>click</td>
<td>css=option[value=&quot;4&quot;]</td>
<td></td>
</tr>
</tbody></table>
</body>
</html>

View File

@ -23,12 +23,14 @@
"grunt-contrib-uglify": "0.2.2",
"grunt-contrib-watch": "0.6.1",
"grunt-express": "1.0",
"grunt-replace": "0.7.8",
"grunt-ghost": "1.0.12",
"grunt-open": "0.2.3",
"grunt-leading-indent": "0.1.0",
"grunt-closure-tools": "~0.8.3",
"grunt-node-webkit-builder": "0.1.19",
"nodewebkit": "0.8.4"
"nodewebkit": "0.8.4",
"dateformat" : "1.0.8-1.2.3"
},
"window": {
"title": "Piskel",

View File

@ -0,0 +1,38 @@
/************************************************************************************************/
/* Browse local piskels panel */
/************************************************************************************************/
.local-piskel-list {
width: 100%;
}
.local-piskel-item {
height: 3em;
}
.local-piskel-name {
width: 40%;
}
.local-piskel-save-date {
font-weight : normal;
}
.local-piskel-list a {
text-decoration: none;
}
.local-piskel-list a:hover {
text-decoration: underline;
}
.local-piskel-list-head {
font-weight: bold;
color: gold;
}
.local-piskel-load-button,
.local-piskel-delete-button {
width : 75px;
}

View File

@ -0,0 +1,55 @@
/************************************************************************************************/
/* Import dialog */
/************************************************************************************************/
.import-section-preview {
display : inline-block;
height : 60px;
width: 60px;
border : 1px dashed #999;
border-radius: 3px;
}
.dialog-section-title {
display : inline-block;
width: 55px;
}
.import-size-field,
.resize-size-field {
width: 50px;
margin-right: 8px;
text-align: right;
}
.import-size-field:nth-of-type(2),
.resize-size-field:nth-of-type(2) {
margin-left: 5px;
}
.import-image-file-name {
display: inline-block;
overflow: hidden;
height: 2rem;
word-break : break-all;
vertical-align: middle;
font-style: italic;
font-weight: normal;
text-shadow: none;
}
[name=smooth-resize-checkbox] {
margin : 0 8px;
}
.dialog-import-body {
padding:10px 20px;
font-size:1.5em
}
.import-button {
font-size: 1em;
height: auto;
padding: 5px 10px;
}

View File

@ -17,16 +17,16 @@
opacity: 0;
pointer-events: none;
transition: opacity 0.5s;
color: white;
}
#dialog-container-wrapper.animated {
transition: opacity 0.5s;
}
#dialog-container-wrapper.show {
opacity: 1;
pointer-events: auto;
transition: opacity 0.5s;
}
#dialog-container {
@ -34,17 +34,71 @@
height: 100%;
margin-top: -1500px;
transition:margin-top 0.5s;
box-sizing: border-box;
-moz-box-sizing : border-box;
border-radius: 3px;
background: rgba(0,0,0,1);
border : 3px solid gold;
background: #444;
overflow: auto;
}
.animated #dialog-container {
transition:margin-top 0.5s;
}
.show #dialog-container {
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-container.import-image {
width: 500px;
height: 300px;
top : 50%;
left : 50%;
position : absolute;
margin-left: -250px;
}
.show #dialog-container.import-image {
margin-top: -150px;
}
.dialog-wrapper {
position : relative;
}
.dialog-head {
width: 100%;
background: gold;
margin: 0;
padding: 10px;
color: black;
font-size: 1.8em;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.dialog-close {
position: absolute;
top: 0;
right: 0;
line-height: 45px;
margin-right: 10px;
font-size: 1.3em;
cursor: pointer;
}

33
src/css/font-icon.css Normal file
View File

@ -0,0 +1,33 @@
@font-face {
font-family: 'piskel';
src:url('fonts/piskel.eot?-3olv93');
src:url('fonts/piskel.eot?#iefix-3olv93') format('embedded-opentype'),
url('fonts/piskel.woff?-3olv93') format('woff'),
url('fonts/piskel.ttf?-3olv93') format('truetype'),
url('fonts/piskel.svg?-3olv93#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
[class^="piskel-icon-"], [class*=" piskel-icon-"] {
font-family: 'piskel';
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.piskel-icon-eye:before {
content: "\e602";
}
.piskel-icon-onion:before {
content: "\e601";
}

BIN
src/css/fonts/piskel.eot Normal file

Binary file not shown.

13
src/css/fonts/piskel.svg Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="icomoon" horiz-adv-x="512">
<font-face units-per-em="512" ascent="480" descent="-32" />
<missing-glyph horiz-adv-x="512" />
<glyph unicode="&#x20;" d="" horiz-adv-x="256" />
<glyph unicode="&#xe600;" d="M548.568 479.997c-230.956 1.035-548.568-255.999-548.568-255.999s288.019-255.998 548.568-255.998c229.744 0 548.568 255.999 548.568 255.999s-319.896 254.974-548.568 255.999zM543.082 398.397c100.382 0 181.713-81.33 181.713-181.713s-81.331-181.713-181.713-181.713c-100.382 0-181.827 81.331-181.827 181.713s81.445 181.713 181.827 181.713zM543.197 331.312c-65.289 0-118.285-52.996-118.285-118.285s52.996-118.171 118.285-118.171c65.289 0 118.17 52.882 118.17 118.171s-52.882 118.285-118.17 118.285z" horiz-adv-x="1097" />
<glyph unicode="&#xe601;" d="M333.139 442.196l-28.111-24.945-1.682 9.117-16.077-4.654v-31.086l1.038-22.032 30.642 27.192c-0.394-5.602-0.579-11.514-0.189-18.076 0.616-10.389 3.469-19.727 9.148-27.036s13.329-11.986 21.812-15.858c16.965-7.745 38.105-20.45 64.012-41.986 49.053-40.769 55.122-61.117 63.962-96.969 8.416-46.603-4.959-80.166-24.261-108.637-13.789-20.344-30.859-38.395-68.38-46.004s-72.657-10.067-97.784-10.067v-25.324c26.745 0 62.98 2.493 102.815 10.574s79.13 21.041 103.132 46.154c25.984 27.183 50.821 76.445 35.96 153.464l-0.063 0.253c-6.619 30.719-26.716 76.854-105.285 111.015-32.5 14.131-50.132 23.25-63.389 29.304-6.628 3.027-10.442 6.947-12.524 9.622s-3.445 5.956-3.862 12.978c-0.939 15.803 1.36 27.825 3.767 35.771s4.432 11.015 4.432 11.015l-19.12 16.209zM305.535 392.371c0 0-18.259 4.773-18.259-1.332 0-33.82-0.462-39.793 11.136-63.691s26.568-48.483 49.166-69.349c42.733-39.459 39.275-45.454 46.367-65.753 2.611-7.473 3.713-24.832 1.899-38.462s-6.896-31.623-13.579-41.846c-10.502-16.069-18.963-32.495-39.053-43.653-20.991-11.659-39.094-14.177-55.936-14.177v-25.324c21.094 0 45.108 5.082 70.464 15.322s49.766 25.601 64.546 48.212c9.899 15.147 20.321 38.209 22.622 56.641s6.87 34.332-5.148 59.162c-18.5 38.219-43.101 49.697-73.135 75.121-18.592 15.74-35.31 34.27-45.45 55.156s-15.009 42.098-15.636 53.973zM302.18 376.1l-14.906-1.362c0.757-14.293 0-43.707 0-71.637 0-13.26 2.204-29.37 4.278-40.492 3.993-21.428 10.649-35.336 14.823-48.794 3.317-10.697 7.035-25.671 9.51-31.424 6.695-15.587 7.627-34.636 0.765-56.569-6.95-22.212-17.785-43.502-35.888-50.49l6.513-21.476c26.197 10.113 62.845 38.626 72.867 70.666 9.036 28.875 3.329 54.971-4.906 74.137-4.993 11.622-9.74 19.624-15.059 29.314-6.544 11.921-20.45 26.866-24.431 39.038-3.621 11.070-7.929 24.458-9.038 38.151-2.22 27.384-3.681 55.489-4.526 70.94zM243.043 442.167l28.111-24.945 1.682 9.117 16.077-4.654v-31.086l-1.038-22.031-30.642 27.192c0.394-5.601 0.579-11.514 0.189-18.076-0.616-10.391 0.623-20.75-5.055-28.057s-12.305-17.102-20.787-20.976c-16.965-7.747-37.083-20.449-62.988-41.986-49.053-40.769-47.959-51.909-56.799-87.761-3.299-47.627-5.999-46.959 4.819-79.986 6.537-19.959 22.674-39.417 60.195-57.258 34.577-16.442 86.982-30.531 112.107-30.531v-25.324c-26.745 0-62.98 2.493-102.815 10.57s-79.129 21.041-103.132 46.154c-25.983 27.182-50.821 76.447-35.959 153.464l0.063 0.253c6.618 30.719 26.715 76.854 105.288 111.015 32.499 14.131 50.131 23.25 63.386 29.302 6.629 3.026 10.442 6.948 12.528 9.622s3.445 5.956 3.862 12.978c0.939 15.803-1.36 27.825-3.767 35.771s-4.431 11.015-4.431 11.015l19.12 16.207zM281.173 395.236l9.119-12.938c-0.757-14.293 0-43.707 0-71.637 0-13.261 3.582-30.816 1.509-41.939-3.993-21.428-3.416-28.824-7.589-42.282-3.317-10.697-7.035-29.287-9.51-35.043-6.695-15.587-8.351-51.277-1.488-73.21 6.95-22.212 11.272-50.74 22.139-67.131l4.043-41.683c-24.026 32.543-48.269 69.938-58.294 101.975-9.036 28.875-8.394 79.572-0.158 98.736 4.993 11.622 9.74 23.244 15.059 32.931 6.544 11.922 10.268 23.796 13.227 36.99 2.548 11.365 7.031 29.873 8.139 43.568 2.22 27.387 2.957 56.213 3.804 71.663z" horiz-adv-x="576" />
<glyph unicode="&#xe602;" d="M256 384c-111.659 0-208.441-65.021-256-160 47.559-94.979 144.341-160 256-160 111.657 0 208.439 65.021 256 160-47.558 94.979-144.343 160-256 160zM382.225 299.148c30.081-19.187 55.571-44.887 74.717-75.148-19.146-30.261-44.637-55.961-74.718-75.149-37.797-24.108-81.445-36.851-126.224-36.851-44.78 0-88.428 12.743-126.225 36.852-30.080 19.186-55.57 44.886-74.717 75.148 19.146 30.262 44.637 55.962 74.717 75.148 1.959 1.25 3.938 2.461 5.929 3.65-4.979-13.664-7.704-28.411-7.704-43.798 0-70.692 57.308-128 128-128s128 57.308 128 128c0 15.387-2.725 30.134-7.704 43.799 1.99-1.189 3.969-2.401 5.929-3.651zM256 275c0-26.51-21.49-48-48-48s-48 21.49-48 48 21.49 48 48 48 48-21.49 48-48z" />
</font></defs></svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
src/css/fonts/piskel.ttf Normal file

Binary file not shown.

BIN
src/css/fonts/piskel.woff Normal file

Binary file not shown.

View File

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

View File

@ -33,4 +33,8 @@ ul, li {
::-webkit-scrollbar-track {
background-color: rgba(50, 50, 50, 0.4);
}
a, a:visited {
color:gold;
}

View File

@ -1,35 +1,42 @@
/*******************************/
/* Gif/Png Export Setting panel*/
/*******************************/
.gif-upload-button,
.gif-download-button,
.gif-render-button {
/*float : right;*/
margin-top : 10px;
margin-right : 10px;
}
.gif-export-radio-group {
margin:10px 0;
}
.gif-export-preview,
.png-export-preview {
margin-top:20px;
max-width:240px;
position:relative;
margin-top:10px;
max-height:32px;
}
.png-export-preview {
margin:10px 0;
overflow: hidden;
.gif-export-preview {
max-width:32px;
}
.png-export-preview img {
max-height:32px;
float: left;
}
.png-upload-status {
margin : 10px 0;
.gif-upload-status {
width: 180px;
margin-left: 5px;
margin-top: 10px;
}
.gif-upload,
.png-export-preview {
overflow: hidden;
}
.gif-upload-status,
.gif-export-preview {
float : left;
}
.preview-upload-ongoing:before{
@ -44,4 +51,15 @@
-moz-box-sizing:border-box;
background: rgba(0,0,0,0.5);
color: white;
}
}
.gif-export-progress-status {
margin-left: 5px;
}
.gif-export-progress-bar {
margin-top:5px;
height:3px;
width: 0;
background:gold;
}

18
src/css/settings-import.css vendored Normal file
View File

@ -0,0 +1,18 @@
/************************************************************************************************/
/* Import panel */
/************************************************************************************************/
.import-section,
.resize-section {
margin: 10px 0;
}
.file-input-button {
margin-right: 8px;
border-radius: 2px;
}
.import-highlight {
font-weight: bold;
color: white;
}

View File

@ -49,9 +49,9 @@
background-size: 32px 32px;
}
.tool-icon.upload-cloud-icon {
background-image: url(../img/cloud_export.png);
background-position: 4px 0px;
.tool-icon.export-icon {
background-image: url(../img/export.png);
background-position: 7px 5px;
background-size: 36px 36px;
position: relative;
}
@ -70,7 +70,7 @@
position: relative;
}
.upload-cloud-icon .label {
.tool-icon .label {
position: absolute;
left: 0;
bottom: 4px;
@ -121,11 +121,13 @@
}
.settings-title {
color : gold;
margin-top: 20px;
margin-bottom: 10px;
text-transform: uppercase;
border-bottom: 1px #aaa solid;
padding-bottom: 5px;
color: gold;
}
.settings-description {
@ -141,6 +143,10 @@
margin : 10px 0;
}
[name*=checkbox] {
vertical-align: middle;
}
/************************************************************************************************/
/* Application settings */
/************************************************************************************************/
@ -178,176 +184,28 @@
border: gold 1px solid;
}
/************************************************************************************************/
/* Gif/Png Export panel */
/************************************************************************************************/
.gif-upload-button,
.gif-render-button {
margin-top : 10px;
margin-right : 10px;
}
.gif-export-radio-group {
margin:10px 0;
}
.gif-export-progress-status {
margin-left: 5px;
}
.gif-export-progress-bar {
margin-top:5px;
height:3px;
width: 0;
background:gold;
}
.gif-export-preview,
.png-export-preview {
margin-top:20px;
max-width:240px;
position:relative;
}
.png-export-preview {
margin:10px 0;
overflow: hidden;
}
.png-export-preview img {
float: left;
}
.png-upload-status {
margin : 10px 0;
}
.preview-upload-ongoing:before{
content: "Upload ongoing ...";
position: absolute;
display: block;
height: 100%;
width: 100%;
text-align: center;
padding-top: 45%;
box-sizing:border-box;
-moz-box-sizing:border-box;
background: rgba(0,0,0,0.5);
color: white;
}
/************************************************************************************************/
/* Import panel */
/* Save panel */
/************************************************************************************************/
.import-section,
.resize-section {
margin: 15px 0;
}
.import-section-title {
display : inline-block;
}
.import-section-title-small {
width: 35px;
}
.import-section-disabled {
color : #888;
}
.import-section-preview {
display : inline-block;
height : 60px;
width: 60px;
border : 1px dashed #999;
border-radius: 3px;
}
.import-size-field,
.resize-size-field {
width: 50px;
margin-right: 8px;
text-align: right;
}
.import-size-field:nth-of-type(2),
.resize-size-field:nth-of-type(2) {
margin-left: 5px;
}
.file-input-button {
margin-right: 8px;
border-radius: 2px;
}
.file-input-status {
display: inline-block;
width: 130px;
overflow: hidden;
height: 1.5rem;
word-break : break-all;
vertical-align: middle;
font-style: italic;
font-weight: normal;
text-shadow: none;
}
.save-field {
width: 100%;
}
#save-status {
.save-status {
margin-top: 10px;
}
.status {
height: 1.5rem;
margin-bottom: -10px;
vertical-align: middle;
font-weight: normal;
text-shadow: none;
font-style: italic;
}
[name=smooth-resize-checkbox] {
margin : 0 8px;
}
[name*=checkbox] {
vertical-align: middle;
}
/************************************************************************************************/
/* Browse local piskels panel */
/************************************************************************************************/
.local-piskels-list {
width: 100%;
}
.local-piskel-item {
height: 3em;
}
.local-piskel-name {
width: 40%;
}
.local-piskel-save-date {
font-weight : normal;
}
.local-piskels-list a {
text-decoration: none;
}
.local-piskels-list a:hover {
text-decoration: underline;
}
.local-piskel-load-link {
color : gold;
}
.local-piskel-delete-link {
color : red;
.save-file-name {
white-space: nowrap;
font-weight: bold;
color: white;
font-style: normal;
}

View File

@ -158,62 +158,11 @@ body {
*/
.canvas.layers-below-canvas {z-index: 7;}
.canvas.drawing-canvas {z-index: 8;}
.canvas.layers-above-canvas {z-index: 9;}
.canvas.onion-skin-canvas {z-index: 10;}
.canvas.canvas-overlay {z-index: 11;}
.canvas.canvas-overlay {z-index: 9;}
.canvas.onion-skin-canvas {z-index: 10;}
.canvas.layers-above-canvas {z-index: 11;}
/**
* Animated preview styles.
*/
.preview-container {
border : 0px Solid black;
border-radius:5px 0px 0px 5px;
box-shadow : 0px 0px 2px rgba(0,0,0,0.2);
font-size: 0;
}
.preview-container .canvas-container {
overflow : hidden;
}
.preview-container canvas {
border : 0px Solid transparent;
}
#animated-preview-container {
background: #333;
border-radius : 0 0 2px 2px;
overflow : hidden;
}
#animated-preview-canvas-container {
height :200px;
width : 200px;
}
.tiled-frame-container {
height: 100%;
width: 100%;
position: relative;
background-repeat : repeat;
}
.display-fps {
float: left;
color: #aaa;
font-size: 12px;
min-width: 55px;
vertical-align: bottom;
line-height: 24px;
}
.range-fps {
overflow: hidden;
width: 120px;
height : 24px;
margin : 0;
}
/**
* User messages

View File

@ -0,0 +1,76 @@
/**
* Animated preview styles.
*/
.preview-container {
border : 0px Solid black;
border-radius:5px 0px 0px 5px;
box-shadow : 0px 0px 2px rgba(0,0,0,0.2);
font-size: 0;
}
.preview-container .canvas-container {
overflow : hidden;
}
.preview-container canvas {
border : 0px Solid transparent;
}
#animated-preview-container {
background: #333;
border-radius : 0 0 2px 2px;
overflow : hidden;
}
#animated-preview-canvas-container {
height :200px;
width : 200px;
}
.tiled-frame-container {
height: 100%;
width: 100%;
position: relative;
background-repeat : repeat;
}
.display-fps {
float: left;
color: #aaa;
font-size: 12px;
min-width: 55px;
vertical-align: bottom;
line-height: 26px;
}
.range-fps {
overflow: hidden;
width: 100px;
height : 26px;
margin : 0;
box-sizing: border-box;
padding:0;
}
.preview-toggle-onion-skin {
font-size: 2rem;
color: #aaa;
float: left;
line-height: 26px;
height: 100%;
padding-left: 5px;
padding-right: 5px;
border-right: 1px solid #222;
transition: 0.2s linear;
cursor:pointer;
}
.preview-toggle-onion-skin:hover {
color : white;
}
.preview-toggle-onion-skin-enabled,
.preview-toggle-onion-skin-enabled:hover {
color : gold;
}

View File

@ -10,6 +10,28 @@
background-size: 22px;
background-repeat: no-repeat;
background-position: 97%;
position: relative;
}
.layers-toggle-preview {
position: absolute;
top: 0.3em;
right: 2em;
color: #999;
font-size: 1.3em;
cursor: pointer;
transition: 0.2s linear;
}
.layers-toggle-preview:hover {
color: white;
}
.layers-toggle-preview-enabled,
.layers-toggle-preview-enabled:hover {
color : gold;
}
.layers-list {

View File

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

BIN
src/img/export.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 734 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -22,7 +22,11 @@
color:white;">
<span style="top:45%">Loading Piskel ...</span>
</div>
<script type="text/javascript" src="js/lib/iframeLoader.js"></script>
<script type="text/javascript" src="js/lib/iframeLoader-0.1.0.js"></script>
<!-- the comment below indicates the beginning of markup reused by the editor integrated in piskelapp.com -->
<!-- do not delete, do not move :) -->
<!--body-main-start-->
<div id="main-wrapper" class="main-wrapper">
<iframe src="templates/drawing-tools.html" onload="iframeloader.onLoad(event)" data-iframe-loader="display"></iframe>
@ -50,13 +54,11 @@
<iframe src="templates/settings.html" onload="iframeloader.onLoad(event)" data-iframe-loader="display"></iframe>
<div class="drawer vertical-centerer">
<div class="drawer-content" id="drawer-container">
<iframe src="templates/settings/save.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/settings/application.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/settings/resize.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/settings/save.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/settings/import.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/settings/localstorage.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/settings/export-gif.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/settings/export-png.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/settings/export.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
</div>
</div>
</div>
@ -66,10 +68,16 @@
<div id="dialog-container-wrapper">
<div id="dialog-container">
<iframe src="templates/dialogs/manage-palettes.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/dialogs/import-image.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/dialogs/browse-local.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
</div>
</div>
<iframe src="templates/cheatsheet.html" onload="iframeloader.onLoad(event)" data-iframe-loader="display"></iframe>
<script type="text/javascript" src="piskel-boot.js"></script>
<!--body-main-end-->
<!-- the comment above indicates the end of the markup reused by the editor integrated in piskelapp.com -->
<!-- do not delete, do not move :) -->
<script type="text/javascript" src="piskel-boot-0.1.0.js"></script>
</body>
</html>

View File

@ -11,6 +11,8 @@ var Constants = {
MAX_HEIGHT : 1024,
MAX_WIDTH : 1024,
MAX_CURRENT_COLORS_DISPLAYED : 100,
MINIMUM_ZOOM : 1,
PREVIEW_FILM_SIZE : 96,

View File

@ -99,6 +99,14 @@
this.savedStatusService = new pskl.service.SavedStatusService(this.piskelController);
this.savedStatusService.init();
this.backupService = new pskl.service.BackupService(this.piskelController);
this.backupService.init();
this.beforeUnloadService = new pskl.service.BeforeUnloadService(this.piskelController);
this.beforeUnloadService.init();
this.fileDropperService = new pskl.service.FileDropperService(this.piskelController, $('#drawing-canvas-container').get(0));
this.fileDropperService.init();
if (this.isAppEngineVersion) {
this.storageService = new pskl.service.AppEngineStorageService(this.piskelController);
@ -164,3 +172,4 @@
}
};
})();

View File

@ -16,14 +16,43 @@
var frame = this.piskelController.getCurrentFrame();
this.renderer = new pskl.rendering.frame.TiledFrameRenderer(this.container);
this.updateZoom_();
$.subscribe(Events.FRAME_SIZE_CHANGED, this.onFrameSizeChange_.bind(this));
$.subscribe(Events.USER_SETTINGS_CHANGED, $.proxy(this.onUserSettingsChange_, this));
};
ns.AnimatedPreviewController.prototype.onUserSettingsChange_ = function () {
ns.AnimatedPreviewController.prototype.init = function () {
// the oninput event won't work on IE10 unfortunately, but at least will provide a
// consistent behavior across all other browsers that support the input type range
// see https://bugzilla.mozilla.org/show_bug.cgi?id=853670
$("#preview-fps")[0].addEventListener('change', this.onFPSSliderChange.bind(this));
document.querySelector(".right-column").style.width = Constants.ANIMATED_PREVIEW_WIDTH + 'px';
this.toggleOnionSkinEl = document.querySelector(".preview-toggle-onion-skin");
this.toggleOnionSkinEl.addEventListener('click', this.toggleOnionSkin_.bind(this));
pskl.app.shortcutService.addShortcut('alt+O', this.toggleOnionSkin_.bind(this));
$.subscribe(Events.FRAME_SIZE_CHANGED, this.onFrameSizeChange_.bind(this));
$.subscribe(Events.USER_SETTINGS_CHANGED, $.proxy(this.onUserSettingsChange_, this));
this.updateZoom_();
this.updateContainerDimensions_();
this.updateOnionSkinPreview_();
};
ns.AnimatedPreviewController.prototype.onUserSettingsChange_ = function (evt, name, value) {
if (name == pskl.UserSettings.ONION_SKIN) {
this.updateOnionSkinPreview_();
} else {
this.updateZoom_();
this.updateContainerDimensions_();
}
};
ns.AnimatedPreviewController.prototype.updateOnionSkinPreview_ = function () {
var enabledClassname = 'preview-toggle-onion-skin-enabled';
if (pskl.UserSettings.get(pskl.UserSettings.ONION_SKIN)) {
this.toggleOnionSkinEl.classList.add(enabledClassname);
} else {
this.toggleOnionSkinEl.classList.remove(enabledClassname);
}
};
ns.AnimatedPreviewController.prototype.updateZoom_ = function () {
@ -47,22 +76,16 @@
};
};
ns.AnimatedPreviewController.prototype.init = function () {
// the oninput event won't work on IE10 unfortunately, but at least will provide a
// consistent behavior across all other browsers that support the input type range
// see https://bugzilla.mozilla.org/show_bug.cgi?id=853670
$("#preview-fps")[0].addEventListener('change', this.onFPSSliderChange.bind(this));
document.querySelector(".right-column").style.width = Constants.ANIMATED_PREVIEW_WIDTH + 'px';
};
ns.AnimatedPreviewController.prototype.onFPSSliderChange = function (evt) {
this.setFPS(parseInt($("#preview-fps")[0].value, 10));
};
ns.AnimatedPreviewController.prototype.setFPS = function (fps) {
this.fps = fps;
$("#preview-fps").val(this.fps);
$("#display-fps").html(this.fps + " FPS");
if (fps) {
this.fps = fps;
$("#preview-fps").val(this.fps);
$("#display-fps").html(this.fps + " FPS");
}
};
ns.AnimatedPreviewController.prototype.getFPS = function () {
@ -122,4 +145,9 @@
containerEl.style.marginLeft = ((PREVIEW_SIZE - width) / 2) + "px";
containerEl.style.marginRight = ((PREVIEW_SIZE - width) / 2) + "px";
};
ns.AnimatedPreviewController.prototype.toggleOnionSkin_ = function () {
var currentValue = pskl.UserSettings.get(pskl.UserSettings.ONION_SKIN);
pskl.UserSettings.set(pskl.UserSettings.ONION_SKIN, !currentValue);
};
})();

View File

@ -113,7 +113,7 @@
ns.DrawingController.prototype.onUserSettingsChange_ = function (evt, settingsName, settingsValue) {
if(settingsName == pskl.UserSettings.SHOW_GRID) {
console.warn('DrawingController:onUserSettingsChange_ not implemented !');
} else if (settingsName == pskl.UserSettings.OVERLAY) {
} else if (settingsName == pskl.UserSettings.ONION_SKIN || settingsName == pskl.UserSettings.LAYER_PREVIEW) {
this.onionSkinRenderer.clear();
this.onionSkinRenderer.flush();
this.layersRenderer.clear();
@ -271,10 +271,13 @@
};
/**
* @private
* Translate absolute x,y screen coordinates into sprite coordinates
* @param {Number} screenX
* @param {Number} screenY
* @return {Object} {x:Number, y:Number}
*/
ns.DrawingController.prototype.getSpriteCoordinates = function(event) {
return this.renderer.getCoordinates(event.clientX, event.clientY);
ns.DrawingController.prototype.getSpriteCoordinates = function(screenX, screenY) {
return this.renderer.getCoordinates(screenX, screenY);
};
ns.DrawingController.prototype.setCurrentButton = function (event) {
@ -319,10 +322,11 @@
this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(currentFrame);
}
var overlaySetting = pskl.UserSettings.get(pskl.UserSettings.OVERLAY);
if (overlaySetting === Constants.OVERLAY_ONION_SKIN) {
if (pskl.UserSettings.get(pskl.UserSettings.ONION_SKIN)) {
this.onionSkinRenderer.render();
} else if (overlaySetting === Constants.OVERLAY_LAYER_PREVIEW) {
}
if (pskl.UserSettings.get(pskl.UserSettings.LAYER_PREVIEW)) {
this.layersRenderer.render();
}

View File

@ -7,14 +7,21 @@
ns.LayersListController.prototype.init = function () {
this.layerItemTemplate_ = pskl.utils.Template.get('layer-item-template');
this.rootEl = document.querySelectorAll('.layers-list-container')[0];
this.layersListEl = document.querySelectorAll('.layers-list')[0];
this.rootEl = document.querySelector('.layers-list-container');
this.layersListEl = document.querySelector('.layers-list');
this.toggleLayerPreviewEl = document.querySelector('.layers-toggle-preview');
this.rootEl.addEventListener('click', this.onClick_.bind(this));
this.toggleLayerPreviewEl.addEventListener('click', this.toggleLayerPreview_.bind(this));
$.subscribe(Events.PISKEL_RESET, this.renderLayerList_.bind(this));
pskl.app.shortcutService.addShortcut('alt+L', this.toggleLayerPreview_.bind(this));
this.renderLayerList_();
this.updateToggleLayerPreview_();
$.subscribe(Events.USER_SETTINGS_CHANGED, $.proxy(this.onUserSettingsChange_, this));
};
ns.LayersListController.prototype.renderLayerList_ = function () {
@ -23,6 +30,21 @@
layers.forEach(this.addLayerItem.bind(this));
};
ns.LayersListController.prototype.updateToggleLayerPreview_ = function () {
var enabledClassname = 'layers-toggle-preview-enabled';
if (pskl.UserSettings.get(pskl.UserSettings.LAYER_PREVIEW)) {
this.toggleLayerPreviewEl.classList.add(enabledClassname);
} else {
this.toggleLayerPreviewEl.classList.remove(enabledClassname);
}
};
ns.LayersListController.prototype.onUserSettingsChange_ = function (evt, name, value) {
if (name == pskl.UserSettings.LAYER_PREVIEW) {
this.updateToggleLayerPreview_();
}
};
ns.LayersListController.prototype.addLayerItem = function (layer, index) {
var isSelected = this.piskelController.getCurrentLayer() === layer;
var layerItemHtml = pskl.utils.Template.replace(this.layerItemTemplate_, {
@ -69,4 +91,9 @@
this.piskelController.removeCurrentLayer();
}
};
ns.LayersListController.prototype.toggleLayerPreview_ = function () {
var currentValue = pskl.UserSettings.get(pskl.UserSettings.LAYER_PREVIEW);
pskl.UserSettings.set(pskl.UserSettings.LAYER_PREVIEW, !currentValue);
};
})();

View File

@ -10,7 +10,6 @@
// I apologize to my future self for this one.
var NO_SCROLL_MAX_COLORS = 20;
var MAX_COLORS = 100;
ns.PalettesListController = function (paletteController, usedColorService) {
this.usedColorService = usedColorService;
@ -80,8 +79,8 @@
}
}
if (colors.length > MAX_COLORS) {
colors = colors.slice(0, MAX_COLORS);
if (colors.length > Constants.MAX_CURRENT_COLORS_DISPLAYED) {
colors = colors.slice(0, Constants.MAX_CURRENT_COLORS_DISPLAYED);
}
return colors;

View File

@ -15,6 +15,10 @@
this.refreshZoom_();
this.redrawFlag = true;
this.cachedFrameProcessor = new pskl.model.frame.CachedFrameProcessor();
this.cachedFrameProcessor.setFrameProcessor(this.frameToPreviewCanvas_.bind(this));
this.cachedFrameProcessor.setOutputCloner(this.clonePreviewCanvas_.bind(this));
};
ns.PreviewFilmController.prototype.init = function() {
@ -39,7 +43,6 @@
ns.PreviewFilmController.prototype.render = function () {
if (this.redrawFlag) {
// TODO(vincz): Full redraw on any drawing modification, optimize.
this.createPreviews_();
this.redrawFlag = false;
}
@ -77,7 +80,6 @@
if (action === ACTION.CLONE) {
this.piskelController.duplicateFrameAt(index);
this.piskelController.setCurrentFrameIndex(index + 1);
this.updateScrollerOverflows();
} else if (action === ACTION.DELETE) {
this.piskelController.removeFrameAt(index);
@ -86,7 +88,6 @@
this.piskelController.setCurrentFrameIndex(index);
} else if (action === ACTION.NEW_FRAME) {
this.piskelController.addFrame();
this.piskelController.setCurrentFrameIndex(this.piskelController.getFrameCount() - 1);
this.updateScrollerOverflows();
}
};
@ -175,11 +176,8 @@
cloneFrameButton.className = "tile-overlay duplicate-frame-action";
previewTileRoot.appendChild(cloneFrameButton);
var canvasRenderer = new pskl.rendering.CanvasRenderer(currentFrame, this.zoom);
canvasRenderer.drawTransparentAs(Constants.TRANSPARENT_COLOR);
var canvas = canvasRenderer.render();
canvas.classList.add('tile-view', 'canvas');
canvasContainer.appendChild(canvas);
canvasContainer.appendChild(this.getCanvasForFrame(currentFrame));
previewTileRoot.appendChild(canvasContainer);
if(tileNumber > 0 || this.piskelController.getFrameCount() > 1) {
@ -206,6 +204,25 @@
return previewTileRoot;
};
ns.PreviewFilmController.prototype.getCanvasForFrame = function (frame) {
var canvas = this.cachedFrameProcessor.get(frame, this.zoom);
return canvas;
};
ns.PreviewFilmController.prototype.frameToPreviewCanvas_ = function (frame) {
var canvasRenderer = new pskl.rendering.CanvasRenderer(frame, this.zoom);
canvasRenderer.drawTransparentAs(Constants.TRANSPARENT_COLOR);
var canvas = canvasRenderer.render();
canvas.classList.add('tile-view', 'canvas');
return canvas;
};
ns.PreviewFilmController.prototype.clonePreviewCanvas_ = function (canvas) {
var clone = pskl.CanvasUtils.clone(canvas);
clone.classList.add('tile-view', 'canvas');
return clone;
};
/**
* Calculate the preview zoom depending on the piskel size
*/

View File

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

View File

@ -0,0 +1,18 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs');
ns.AbstractDialogController = function () {};
ns.AbstractDialogController.prototype.init = function () {
this.closeButton = document.querySelector('.dialog-close');
this.closeButton.addEventListener('click', this.closeDialog.bind(this));
};
ns.AbstractDialogController.prototype.destroy = function () {};
ns.AbstractDialogController.prototype.closeDialog = function () {
$.publish(Events.DIALOG_HIDE);
};
})();

View File

@ -0,0 +1,57 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs');
ns.BrowseLocalController = function (piskelController) {
};
pskl.utils.inherit(ns.BrowseLocalController, ns.AbstractDialogController);
ns.BrowseLocalController.prototype.init = function () {
this.superclass.init.call(this);
this.localStorageItemTemplate_ = pskl.utils.Template.get("local-storage-item-template");
this.service_ = pskl.app.localStorageService;
this.piskelList = $('.local-piskel-list');
this.prevSessionContainer = $('.previous-session');
this.fillLocalPiskelsList_();
this.piskelList.click(this.onPiskelsListClick_.bind(this));
};
ns.BrowseLocalController.prototype.onPiskelsListClick_ = function (evt) {
var action = evt.target.getAttribute('data-action');
var name = evt.target.getAttribute('data-name');
if (action === 'load') {
if (window.confirm('This will erase your current piskel. Continue ?')) {
this.service_.load(name);
this.closeDialog();
}
} else if (action === 'delete') {
if (window.confirm('This will permanently DELETE this piskel from your computer. Continue ?')) {
this.service_.remove(name);
this.fillLocalPiskelsList_();
}
}
};
ns.BrowseLocalController.prototype.fillLocalPiskelsList_ = function () {
var html = "";
var keys = this.service_.getKeys();
keys.sort(function (k1, k2) {
if (k1.date < k2.date) {return 1;}
if (k1.date > k2.date) {return -1;}
return 0;
});
keys.forEach((function (key) {
var date = pskl.utils.DateUtils.format(key.date, "{{Y}}/{{M}}/{{D}} {{H}}:{{m}}");
html += pskl.utils.Template.replace(this.localStorageItemTemplate_, {name : key.name, date : date});
}).bind(this));
var tableBody_ = this.piskelList.get(0).tBodies[0];
tableBody_.innerHTML = html;
};
})();

View File

@ -5,6 +5,14 @@
'manage-palettes' : {
template : 'templates/dialogs/manage-palettes.html',
controller : ns.PaletteManagerController
},
'browse-local' : {
template : 'templates/dialogs/browse-local.html',
controller : ns.BrowseLocalController
},
'import-image' : {
template : 'templates/dialogs/import-image.html',
controller : ns.ImportImageController
}
};
@ -20,15 +28,25 @@
$.subscribe(Events.DIALOG_HIDE, this.onDialogHideEvent_.bind(this));
pskl.app.shortcutService.addShortcut('alt+P', this.onDialogDisplayEvent_.bind(this, null, 'manage-palettes'));
this.dialogWrapper_.classList.add('animated');
};
ns.DialogsController.prototype.onDialogDisplayEvent_ = function (evt, dialogId) {
ns.DialogsController.prototype.onDialogDisplayEvent_ = function (evt, args) {
var dialogId, initArgs;
if (typeof args === 'string') {
dialogId = args;
} else {
dialogId = args.dialogId;
initArgs = args.initArgs;
}
if (!this.isDisplayed()) {
var config = dialogs[dialogId];
if (config) {
this.dialogContainer_.innerHTML = pskl.utils.Template.get(config.template);
this.dialogContainer_.classList.add(dialogId);
var controller = new config.controller(this.piskelController);
controller.init();
controller.init(initArgs);
this.showDialogWrapper_();
this.currentDialog_ = {
@ -54,6 +72,10 @@
var currentDialog = this.currentDialog_;
if (currentDialog) {
currentDialog.controller.destroy();
var dialogId = this.currentDialog_.id;
window.setTimeout(function () {
this.dialogContainer_.classList.remove(dialogId);
}.bind(this), 800);
}
this.hideDialogWrapper_();

View File

@ -0,0 +1,154 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs');
var PREVIEW_HEIGHT = 60;
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.resizeWidth = $('[name=resize-width]');
this.resizeHeight = $('[name=resize-height]');
this.smoothResize = $('[name=smooth-resize-checkbox]');
this.resizeWidth.keyup(this.onResizeInputKeyUp_.bind(this, 'width'));
this.resizeHeight.keyup(this.onResizeInputKeyUp_.bind(this, 'height'));
this.importImageForm = $('[name=import-image-form]');
this.importImageForm.submit(this.onImportFormSubmit_.bind(this));
pskl.utils.FileUtils.readFile(this.file_, this.processImageSource_.bind(this));
};
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.synchronizeResizeFields_ = function (value, from) {
value = parseInt(value, 10);
if (isNaN(value)) {
value = 0;
}
var height = this.importedImage_.height, width = this.importedImage_.width;
if (from === 'width') {
this.resizeHeight.val(Math.round(value * height / width));
} else {
this.resizeWidth.val(Math.round(value * width / height));
}
};
/**
* Create an image from the given source (url or data-url), and onload forward to onImageLoaded
* TODO : should be a generic utility method, should take a callback
* @param {String} imageSource url or data-url, will be used as src for the image
*/
ns.ImportImageController.prototype.processImageSource_ = function (imageSource) {
this.importedImage_ = new Image();
this.importedImage_.onload = this.onImageLoaded_.bind(this);
this.importedImage_.src = imageSource;
};
ns.ImportImageController.prototype.onImageLoaded_ = function (evt) {
var w = this.importedImage_.width,
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.html(fileName);
this.resizeWidth.val(w);
this.resizeHeight.val(h);
this.importPreview.width('auto');
this.importPreview.html('');
this.importPreview.append(this.createImagePreview_());
};
ns.ImportImageController.prototype.createImagePreview_ = function () {
var image = document.createElement('IMG');
image.src = this.importedImage_.src;
image.setAttribute('height', PREVIEW_HEIGHT);
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 () {
var image = this.importedImage_;
if (image) {
if (window.confirm('You are about to create a new Piskel, unsaved changes will be lost.')) {
var gifLoader = new window.SuperGif({
gif : image
});
gifLoader.load({
success : function(){
var images = gifLoader.getFrames().map(function (frame) {
return pskl.CanvasUtils.createFromImageData(frame.data);
});
this.createPiskelFromImages_(images);
this.closeDialog();
}.bind(this),
error : function () {
this.createPiskelFromImages_([image]);
this.closeDialog();
}.bind(this)
});
}
}
};
ns.ImportImageController.prototype.createFramesFromImages_ = function (images) {
var w = this.resizeWidth.val();
var h = this.resizeHeight.val();
var smoothing = !!this.smoothResize.prop('checked');
var frames = images.map(function (image) {
var resizedImage = pskl.utils.ImageResizer.resize(image, w, h, smoothing);
return pskl.utils.FrameUtils.createFromImage(resizedImage);
});
return frames;
};
ns.ImportImageController.prototype.createPiskelFromImages_ = function (images) {
var frames = this.createFramesFromImages_(images);
var layer = pskl.model.Layer.fromFrames('Layer 1', frames);
var descriptor = new pskl.model.piskel.Descriptor('Imported piskel', '');
var piskel = pskl.model.Piskel.fromLayers([layer], descriptor);
pskl.app.piskelController.setPiskel(piskel);
pskl.app.animationController.setFPS(Constants.DEFAULT.FPS);
};
})();

View File

@ -18,13 +18,16 @@
this.spectrumContainers = [];
};
pskl.utils.inherit(ns.PaletteManagerController, ns.AbstractDialogController);
ns.PaletteManagerController.prototype.init = function () {
this.superclass.init.call(this);
this.palettesList = document.querySelector('.palette-manager-list');
this.paletteBody = document.querySelector('.palette-manager-details-body');
this.paletteHead = document.querySelector('.palette-manager-details-head');
this.createButton = document.querySelector('.palette-manager-actions-button[data-action="create"]');
this.saveAllButton = document.querySelector('.palette-manager-actions-button[data-action="save-all"]');
this.closeButton = document.querySelector('.palette-manager-close');
this.colorCardTemplate = pskl.utils.Template.get('palette-color-card-template');
this.newColorTemplate = pskl.utils.Template.get('palette-new-color-template');
@ -37,7 +40,6 @@
this.paletteHead.addEventListener('click', this.delegatedPaletteHeadClick.bind(this));
this.createButton.addEventListener('click', this.onCreateClick_.bind(this));
this.saveAllButton.addEventListener('click', this.saveAll.bind(this));
this.closeButton.addEventListener('click', this.closeDialog.bind(this));
// Init markup
this.createPaletteListMarkup();
@ -52,10 +54,6 @@
this.destroySpectrumPickers();
};
ns.PaletteManagerController.prototype.closeDialog = function () {
$.publish(Events.DIALOG_HIDE);
};
ns.PaletteManagerController.prototype.onCreateClick_ = function (evt) {
this.createPalette();
};

View File

@ -58,6 +58,21 @@
return this.piskel.getLayerAt(index);
};
ns.PiskelController.prototype.hasLayerAt = function (index) {
return !!this.getLayerAt(index);
};
// FIXME ?? No added value compared to getLayerAt ??
// Except normalizing to null if undefined ?? ==> To merge
ns.PiskelController.prototype.getLayerByIndex = function (index) {
var layers = this.getLayers();
if (layers[index]) {
return layers[index];
} else {
return null;
}
};
ns.PiskelController.prototype.getCurrentFrame = function () {
var layer = this.getCurrentLayer();
return layer.getFrameAt(this.currentFrameIndex);
@ -77,10 +92,16 @@
};
ns.PiskelController.prototype.getFrameAt = function (index) {
var hash = [];
var frames = this.getLayers().map(function (l) {
return l.getFrameAt(index);
var frame = l.getFrameAt(index);
hash.push(frame.getHash());
return frame;
});
return pskl.utils.FrameUtils.merge(frames);
var mergedFrame = pskl.utils.FrameUtils.merge(frames);
mergedFrame.id = hash.join('-');
mergedFrame.version = 0;
return mergedFrame;
};
ns.PiskelController.prototype.hasFrameAt = function (index) {
@ -99,6 +120,8 @@
this.getLayers().forEach(function (l) {
l.addFrameAt(this.createEmptyFrame_(), index);
}.bind(this));
this.setCurrentFrameIndex(index);
};
ns.PiskelController.prototype.createEmptyFrame_ = function () {
@ -124,6 +147,7 @@
this.getLayers().forEach(function (l) {
l.duplicateFrameAt(index);
});
this.setCurrentFrameIndex(index+1);
};
ns.PiskelController.prototype.moveFrame = function (fromIndex, toIndex) {
@ -138,7 +162,11 @@
};
ns.PiskelController.prototype.setCurrentFrameIndex = function (index) {
this.currentFrameIndex = index;
if (this.hasFrameAt(index)) {
this.currentFrameIndex = index;
} else {
window.console.error('Could not set current frame index to ' + index);
}
};
ns.PiskelController.prototype.selectNextFrame = function () {
@ -156,7 +184,11 @@
};
ns.PiskelController.prototype.setCurrentLayerIndex = function (index) {
this.currentLayerIndex = index;
if (this.hasLayerAt(index)) {
this.currentLayerIndex = index;
} else {
window.console.error('Could not set current layer index to ' + index);
}
};
ns.PiskelController.prototype.selectLayer = function (layer) {
@ -173,15 +205,6 @@
}
};
ns.PiskelController.prototype.getLayerByIndex = function (index) {
var layers = this.getLayers();
if (layers[index]) {
return layers[index];
} else {
return null;
}
};
ns.PiskelController.prototype.generateLayerName_ = function () {
var name = "Layer " + this.layerIdCounter;
while (this.hasLayerForName_(name)) {

View File

@ -49,7 +49,7 @@
ns.PublicPiskelController.prototype.raiseSaveStateEvent_ = function (fn, args) {
$.publish(Events.PISKEL_SAVE_STATE, {
type : pskl.service.HistoryService.REPLAY,
type : pskl.service.HistoryService.REPLAY_NO_SNAPSHOT,
scope : this,
replay : {
fn : fn,

View File

@ -18,10 +18,6 @@
$('#grid-width').val(gridWidth);
$('#grid-width').change(this.onGridWidthChange.bind(this));
var overlay = pskl.UserSettings.get(pskl.UserSettings.OVERLAY);
$('#overlay').val(overlay);
$('#overlay').change(this.onOverlayChange.bind(this));
// Handle canvas background changes:
$('#background-picker-wrapper').click(this.onBackgroundClick.bind(this));
};
@ -31,11 +27,6 @@
pskl.UserSettings.set(pskl.UserSettings.GRID_WIDTH, parseInt(width, 10));
};
ns.ApplicationSettingsController.prototype.onOverlayChange = function (evt) {
var overlay = $('#overlay').val();
pskl.UserSettings.set(pskl.UserSettings.OVERLAY, overlay);
};
ns.ApplicationSettingsController.prototype.onBackgroundClick = function (evt) {
var target = $(evt.target).closest('.background-picker');
if (target.length) {

View File

@ -1,8 +1,10 @@
(function () {
var ns = $.namespace("pskl.controller.settings");
var URL_MAX_LENGTH = 60;
var URL_MAX_LENGTH = 30;
var MAX_GIF_COLORS = 256;
var MAX_EXPORT_ZOOM = 20;
var DEFAULT_EXPORT_ZOOM = 10;
ns.GifExportController = function (piskelController) {
this.piskelController = piskelController;
@ -13,26 +15,20 @@
* @static
* @type {Array} array of Objects {zoom:{Number}, default:{Boolean}}
*/
ns.GifExportController.RESOLUTIONS = [
{
'zoom' : 1
},{
'zoom' : 5
},{
'zoom' : 10,
'default' : true
},{
'zoom' : 20
}
];
ns.GifExportController.RESOLUTIONS = [];
for (var i = 1 ; i <= MAX_EXPORT_ZOOM ; i++) {
ns.GifExportController.RESOLUTIONS.push({
zoom : i
});
}
ns.GifExportController.prototype.init = function () {
this.radioTemplate_ = pskl.utils.Template.get("gif-export-radio-template");
this.optionTemplate_ = pskl.utils.Template.get("gif-export-option-template");
this.uploadStatusContainerEl = document.querySelector(".gif-upload-status");
this.previewContainerEl = document.querySelector(".gif-export-preview");
this.radioGroupEl = document.querySelector(".gif-export-radio-group");
this.selectResolutionEl = document.querySelector(".gif-export-select-resolution");
this.uploadButton = $(".gif-upload-button");
this.uploadButton.click(this.onUploadButtonClick_.bind(this));
@ -40,12 +36,10 @@
this.downloadButton = $(".gif-download-button");
this.downloadButton.click(this.onDownloadButtonClick_.bind(this));
this.exportForm = $(".gif-export-form");
this.exportProgressStatusEl = document.querySelector('.gif-export-progress-status');
this.exportProgressBarEl = document.querySelector('.gif-export-progress-bar');
this.createRadioElements_();
this.createOptionElements_();
};
ns.GifExportController.prototype.onUploadButtonClick_ = function (evt) {
@ -62,9 +56,8 @@
fps = this.piskelController.getFPS();
this.renderAsImageDataAnimatedGIF(zoom, fps, function (imageData) {
pskl.app.imageUploadService.upload(imageData, this.onImageUploadCompleted_.bind(this));
pskl.utils.ImageToBlob.imageDataToBlob(imageData, "image/gif", function(blob) {
pskl.utils.FileUtils.downloadAsFile(fileName, blob);
pskl.utils.BlobUtils.dataToBlob(imageData, "image/gif", function(blob) {
pskl.utils.FileUtils.downloadAsFile(blob, fileName);
});
}.bind(this));
};
@ -82,43 +75,32 @@
};
ns.GifExportController.prototype.updatePreview_ = function (src) {
this.previewContainerEl.innerHTML = "<div><img style='max-width:240px;' src='"+src+"'/></div>";
this.previewContainerEl.innerHTML = "<div><img style='max-width:32px;' src='"+src+"'/></div>";
};
ns.GifExportController.prototype.getSelectedZoom_ = function () {
var radiosColl = this.exportForm.get(0).querySelectorAll("[name=gif-zoom-level]"),
radios = Array.prototype.slice.call(radiosColl,0);
var selectedRadios = radios.filter(function(radio) {return !!radio.checked;});
if (selectedRadios.length == 1) {
return selectedRadios[0].value;
} else {
throw "Unexpected error when retrieving selected zoom";
}
return this.selectResolutionEl.value;
};
ns.GifExportController.prototype.createRadioElements_ = function () {
ns.GifExportController.prototype.createOptionElements_ = function () {
var resolutions = ns.GifExportController.RESOLUTIONS;
for (var i = 0 ; i < resolutions.length ; i++) {
var radio = this.createRadioForResolution_(resolutions[i]);
this.radioGroupEl.appendChild(radio);
var option = this.createOptionForResolution_(resolutions[i]);
this.selectResolutionEl.appendChild(option);
}
};
ns.GifExportController.prototype.createRadioForResolution_ = function (resolution) {
ns.GifExportController.prototype.createOptionForResolution_ = function (resolution) {
var zoom = resolution.zoom;
var label = zoom*this.piskelController.getWidth() + "x" + zoom*this.piskelController.getHeight();
var value = zoom;
var radioHTML = pskl.utils.Template.replace(this.radioTemplate_, {value : value, label : label});
var radioEl = pskl.utils.Template.createFromHTML(radioHTML);
var isSelected = zoom === DEFAULT_EXPORT_ZOOM;
var selected = isSelected ? 'selected' : '';
var optionHTML = pskl.utils.Template.replace(this.optionTemplate_, {value : value, label : label, selected : selected});
var optionEl = pskl.utils.Template.createFromHTML(optionHTML);
if (resolution['default']) {
var input = radioEl.getElementsByTagName("input")[0];
input.setAttribute("checked", "checked");
}
return radioEl;
return optionEl;
};
ns.GifExportController.prototype.renderAsImageDataAnimatedGIF = function(zoom, fps, cb) {
@ -181,8 +163,10 @@
ns.GifExportController.prototype.shorten_ = function (url, maxLength, suffix) {
if (url.length > maxLength) {
url = url.substring(0, maxLength);
url += suffix;
var index = Math.round((maxLength-suffix.length) / 2);
var part1 = url.substring(0, index);
var part2 = url.substring(url.length - index, url.length);
url = part1 + suffix + part2;
}
return url;
};

View File

@ -0,0 +1,14 @@
(function () {
var ns = $.namespace("pskl.controller.settings");
ns.ImageExportController = function (piskelController) {
this.piskelController = piskelController;
this.pngExportController = new ns.PngExportController(piskelController);
this.gifExportController = new ns.GifExportController(piskelController);
};
ns.ImageExportController.prototype.init = function () {
this.pngExportController.init();
this.gifExportController.init();
};
})();

View File

@ -1,7 +1,5 @@
(function () {
var ns = $.namespace('pskl.controller.settings');
var DEFAULT_FILE_STATUS = 'No file selected ...';
var PREVIEW_HEIGHT = 60;
ns.ImportController = function (piskelController) {
this.piskelController = piskelController;
@ -9,195 +7,111 @@
};
ns.ImportController.prototype.init = function () {
this.importForm = $('[name=import-form]');
this.browseLocalButton = document.querySelector('.browse-local-button');
this.browseLocalButton.addEventListener('click', this.onBrowseLocalClick_.bind(this));
this.hiddenFileInput = $('[name=file-upload-input]');
this.fileInputButton = $('.file-input-button');
this.fileInputStatus = $('.file-input-status');
this.fileInputStatus.html(DEFAULT_FILE_STATUS);
this.importPreview = $('.import-section-preview');
this.resizeWidth = $('[name=resize-width]');
this.resizeHeight = $('[name=resize-height]');
this.smoothResize = $('[name=smooth-resize-checkbox]');
this.submitButton = $('[name=import-submit]');
this.importForm.submit(this.onImportFormSubmit_.bind(this));
this.hiddenFileInput.change(this.onFileUploadChange_.bind(this));
this.fileInputButton = $('.file-input-button');
this.fileInputButton.click(this.onFileInputClick_.bind(this));
this.resizeWidth.keyup(this.onResizeInputKeyUp_.bind(this, 'width'));
this.resizeHeight.keyup(this.onResizeInputKeyUp_.bind(this, 'height'));
this.hiddenOpenPiskelInput = $('[name=open-piskel-input]');
this.hiddenOpenPiskelInput.change(this.onOpenPiskelChange_.bind(this));
this.openPiskelInputButton = $('.open-piskel-button');
this.openPiskelInputButton.click(this.onOpenPiskelClick_.bind(this));
this.prevSessionContainer = $('.previous-session');
this.previousSessionTemplate_ = pskl.utils.Template.get("previous-session-info-template");
this.fillRestoreSession_();
};
ns.ImportController.prototype.reset_ = function () {
this.importForm.get(0).reset();
this.fileInputStatus.html(DEFAULT_FILE_STATUS);
ns.ImportController.prototype.closeDrawer_ = function () {
$.publish(Events.CLOSE_SETTINGS_DRAWER);
};
ns.ImportController.prototype.onResizeInputKeyUp_ = function (from, evt) {
if (this.importedImage_) {
this.synchronizeResizeFields_(evt.target.value, from);
}
};
ns.ImportController.prototype.synchronizeResizeFields_ = function (value, from) {
value = parseInt(value, 10);
if (isNaN(value)) {
value = 0;
}
var height = this.importedImage_.height, width = this.importedImage_.width;
if (from === 'width') {
this.resizeHeight.val(Math.round(value * height / width));
} else {
this.resizeWidth.val(Math.round(value * width / height));
}
};
ns.ImportController.prototype.onImportFormSubmit_ = function (evt) {
evt.originalEvent.preventDefault();
this.importImageToPiskel_();
};
ns.ImportController.prototype.onFileUploadChange_ = function (evt) {
this.importFromFile_();
this.importPictureFromFile_();
};
ns.ImportController.prototype.onFileInputClick_ = function (evt) {
this.hiddenFileInput.click();
};
ns.ImportController.prototype.importFromFile_ = function () {
ns.ImportController.prototype.onOpenPiskelChange_ = function (evt) {
this.openPiskelFile_();
};
ns.ImportController.prototype.onOpenPiskelClick_ = function (evt) {
this.hiddenOpenPiskelInput.click();
};
ns.ImportController.prototype.onBrowseLocalClick_ = function (evt) {
$.publish(Events.DIALOG_DISPLAY, 'browse-local');
this.closeDrawer_();
};
ns.ImportController.prototype.openPiskelFile_ = function () {
var files = this.hiddenOpenPiskelInput.get(0).files;
if (files.length == 1) {
var file = files[0];
if (this.isPiskel_(file)){
pskl.utils.PiskelFileUtils.loadFromFile(file, function (piskel, descriptor, fps) {
piskel.setDescriptor(descriptor);
pskl.app.piskelController.setPiskel(piskel);
pskl.app.animationController.setFPS(fps);
});
this.closeDrawer_();
}
}
};
ns.ImportController.prototype.importPictureFromFile_ = function () {
var files = this.hiddenFileInput.get(0).files;
if (files.length == 1) {
var file = files[0];
if (this.isImage_(file)) {
this.readImageFile_(file);
this.enableDisabledSections_();
$.publish(Events.DIALOG_DISPLAY, {
dialogId : 'import-image',
initArgs : file
});
this.closeDrawer_();
} else {
this.reset_();
this.closeDrawer_();
throw 'File is not an image : ' + file.type;
}
}
};
ns.ImportController.prototype.enableDisabledSections_ = function () {
this.resizeWidth.removeAttr('disabled');
this.resizeHeight.removeAttr('disabled');
this.smoothResize.removeAttr('disabled');
this.submitButton.removeAttr('disabled');
this.fileInputButton.removeClass('button-primary');
this.fileInputButton.blur();
$('.import-section-disabled').removeClass('import-section-disabled');
};
ns.ImportController.prototype.readImageFile_ = function (imageFile) {
pskl.utils.FileUtils.readFile(imageFile, this.processImageSource_.bind(this));
};
/**
* Create an image from the given source (url or data-url), and onload forward to onImageLoaded
* TODO : should be a generic utility method, should take a callback
* @param {String} imageSource url or data-url, will be used as src for the image
*/
ns.ImportController.prototype.processImageSource_ = function (imageSource) {
this.importedImage_ = new Image();
this.importedImage_.onload = this.onImageLoaded_.bind(this);
this.importedImage_.src = imageSource;
};
ns.ImportController.prototype.onImageLoaded_ = function (evt) {
var w = this.importedImage_.width,
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 filePath = this.hiddenFileInput.val();
var fileName = this.extractFileNameFromPath_(filePath);
this.fileInputStatus.html(fileName);
this.resizeWidth.val(w);
this.resizeHeight.val(h);
this.importPreview.width('auto');
this.importPreview.html('');
this.importPreview.append(this.createImagePreview_());
};
ns.ImportController.prototype.createImagePreview_ = function () {
var image = document.createElement('IMG');
image.src = this.importedImage_.src;
image.setAttribute('height', PREVIEW_HEIGHT);
return image;
};
ns.ImportController.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.ImportController.prototype.importImageToPiskel_ = function () {
var image = this.importedImage_;
if (image) {
if (window.confirm('You are about to create a new Piskel, unsaved changes will be lost.')) {
var gifLoader = new window.SuperGif({
gif : image
});
gifLoader.load({
success : function(){
var images = gifLoader.getFrames().map(function (frame) {
return pskl.CanvasUtils.createFromImageData(frame.data);
});
this.createPiskelFromImages_(images);
}.bind(this),
error : function () {
this.createPiskelFromImages_([image]);
}.bind(this)
});
}
}
};
ns.ImportController.prototype.createFramesFromImages_ = function (images) {
var w = this.resizeWidth.val();
var h = this.resizeHeight.val();
var smoothing = !!this.smoothResize.prop('checked');
var frames = images.map(function (image) {
var resizedImage = pskl.utils.ImageResizer.resize(image, w, h, smoothing);
return pskl.utils.FrameUtils.createFromImage(resizedImage);
});
return frames;
};
ns.ImportController.prototype.createPiskelFromImages_ = function (images) {
var frames = this.createFramesFromImages_(images);
var layer = pskl.model.Layer.fromFrames('Layer 1', frames);
var descriptor = new pskl.model.piskel.Descriptor('Imported piskel', '');
var piskel = pskl.model.Piskel.fromLayers([layer], descriptor);
pskl.app.piskelController.setPiskel(piskel);
pskl.app.animationController.setFPS(Constants.DEFAULT.FPS);
this.reset_();
};
ns.ImportController.prototype.isImage_ = function (file) {
return file.type.indexOf('image') === 0;
};
ns.ImportController.prototype.isPiskel_ = function (file) {
return (/\.piskel$/).test(file.name);
};
ns.ImportController.prototype.fillRestoreSession_ = function () {
var previousInfo = pskl.app.backupService.getPreviousPiskelInfo();
if (previousInfo) {
var info = {
name : previousInfo.name,
date : pskl.utils.DateUtils.format(previousInfo.date, "{{H}}:{{m}} - {{Y}}/{{M}}/{{D}}")
};
this.prevSessionContainer.html(pskl.utils.Template.replace(this.previousSessionTemplate_, info));
$(".restore-session-button").click(this.onRestorePreviousSessionClick_.bind(this));
} else {
this.prevSessionContainer.html("No piskel backup was found on this browser.");
}
};
ns.ImportController.prototype.onRestorePreviousSessionClick_ = function () {
if (window.confirm('This will erase your current workspace. Continue ?')) {
pskl.app.backupService.load();
$.publish(Events.CLOSE_SETTINGS_DRAWER);
}
};
})();

View File

@ -1,70 +0,0 @@
(function () {
var ns = $.namespace("pskl.controller.settings");
ns.LocalStorageController = function () {};
/**
* @public
*/
ns.LocalStorageController.prototype.init = function() {
this.localStorageItemTemplate_ = pskl.utils.Template.get("local-storage-item-template");
this.service_ = pskl.app.localStorageService;
this.piskelsList = $('.local-piskels-list');
this.fillLocalPiskelsList_();
this.piskelsList.click(this.onPiskelsListClick_.bind(this));
};
ns.LocalStorageController.prototype.onPiskelsListClick_ = function (evt) {
var action = evt.target.getAttribute('data-action');
var name = evt.target.getAttribute('data-name');
if (action === 'load') {
if (window.confirm('This will erase your current piskel. Continue ?')) {
this.service_.load(name);
$.publish(Events.CLOSE_SETTINGS_DRAWER);
}
} else if (action === 'delete') {
if (window.confirm('This will permanently DELETE this piskel from your computer. Continue ?')) {
this.service_.remove(name);
$.publish(Events.CLOSE_SETTINGS_DRAWER);
}
}
};
ns.LocalStorageController.prototype.fillLocalPiskelsList_ = function () {
var html = "";
var keys = this.service_.getKeys();
var pad = function (num) {
if (num < 10) {
return "0" + num;
} else {
return "" + num;
}
};
keys.sort(function (k1, k2) {
if (k1.date < k2.date) {return 1;}
if (k1.date > k2.date) {return -1;}
return 0;
});
keys.forEach((function (key) {
var date = new Date(key.date);
var formattedDate = pskl.utils.Template.replace("{{Y}}/{{M}}/{{D}} {{H}}:{{m}}", {
Y : date.getFullYear(),
M : pad(date.getMonth() + 1),
D : pad(date.getDate()),
H : pad(date.getHours()),
m : pad(date.getMinutes())
});
html += pskl.utils.Template.replace(this.localStorageItemTemplate_, {name : key.name, date : formattedDate});
}).bind(this));
var tableBody_ = this.piskelsList.get(0).tBodies[0];
tableBody_.innerHTML = html;
};
})();

View File

@ -9,9 +9,7 @@
ns.PngExportController.prototype.init = function () {
this.previewContainerEl = document.querySelectorAll(".png-export-preview")[0];
this.uploadStatusContainerEl = document.querySelectorAll(".png-upload-status")[0];
document.querySelector(".png-upload-button").addEventListener('click', this.onPngUploadButtonClick_.bind(this));
document.querySelector(".png-download-button").addEventListener('click', this.onPngDownloadButtonClick_.bind(this));
document.querySelector(".zip-generate-button").addEventListener('click', this.onZipButtonClick_.bind(this));
@ -21,16 +19,11 @@
ns.PngExportController.prototype.onPngDownloadButtonClick_ = function (evt) {
var fileName = this.getPiskelName_() + '.png';
pskl.utils.ImageToBlob.canvasToBlob(this.getFramesheetAsCanvas(), function(blob) {
pskl.utils.FileUtils.downloadAsFile(fileName, blob);
pskl.utils.BlobUtils.canvasToBlob(this.getFramesheetAsCanvas(), function(blob) {
pskl.utils.FileUtils.downloadAsFile(blob, fileName);
});
};
ns.PngExportController.prototype.onPngUploadButtonClick_ = function (evt) {
this.previewContainerEl.classList.add("preview-upload-ongoing");
pskl.app.imageUploadService.upload(this.getFramesheetAsCanvas().toDataURL("image/png"), this.onImageUploadCompleted_.bind(this));
};
ns.PngExportController.prototype.onZipButtonClick_ = function () {
var zip = new window.JSZip();
@ -43,8 +36,8 @@
var fileName = this.getPiskelName_() + '.zip';
var fileContent = zip.generate({type:"blob"});
pskl.utils.FileUtils.downloadAsFile(fileName, fileContent);
var blob = zip.generate({type:"blob"});
pskl.utils.FileUtils.downloadAsFile(blob, fileName);
};
ns.PngExportController.prototype.getFrameAsCanvas_ = function (frame) {

View File

@ -27,7 +27,6 @@
var width = parseInt(this.resizeWidth.val(), 10);
var height = parseInt(this.resizeHeight.val(), 10);
var resizeContentEnabled = this.isResizeContentEnabled_();
var resizedLayers = this.piskelController.getLayers().map(this.resizeLayer_.bind(this));

View File

@ -9,54 +9,101 @@
* @public
*/
ns.SaveController.prototype.init = function () {
this.saveForm = $('form[name=save-form]');
this.nameInput = $('#save-name');
this.descriptionInput = $('#save-description');
this.isPublicCheckbox = $('input[name=save-public-checkbox]');
this.saveCloudButton = $('#save-cloud-button');
this.saveLocalButton = $('#save-local-button');
// Only available in app-engine mode ...
this.piskelName = $('.piskel-name').get(0);
this.piskelName = document.querySelector('.piskel-name');
this.status = $('#save-status');
this.saveOnlineStatus = $('#save-online-status');
this.saveFileStatus = $('#save-file-status');
this.timestamp = new Date();
var descriptor = this.piskelController.getPiskel().getDescriptor();
this.nameInput.val(descriptor.name);
this.descriptionInput = $('#save-description');
this.descriptionInput.val(descriptor.description);
this.isPublicCheckbox = $('input[name=save-public-checkbox]');
this.isPublicCheckbox.prop('checked', descriptor.isPublic);
this.saveFileButton = $('#save-file-button');
this.saveFileButton.click(this.saveFile_.bind(this));
this.saveLocalButton = $('#save-browser-button');
this.saveLocalButton.click(this.saveLocal_.bind(this));
this.saveOnlineButton = $('#save-online-button');
this.saveOnlineButton.click(this.saveOnline_.bind(this));
this.saveForm = $('form[name=save-form]');
this.saveForm.submit(this.onSaveFormSubmit_.bind(this));
this.nameInput = $('#save-name');
this.nameInput.val(descriptor.name);
this.nameInput.keyup(this.updateLocalStatusFilename_.bind(this));
if (!pskl.app.isLoggedIn()) {
this.saveCloudButton.attr('disabled', 'disabled');
this.status.html('You are not logged in. Only Local Save is available.');
this.saveOnlineButton.hide();
$('.save-public-section').hide();
this.saveOnlineStatus.html(pskl.utils.Template.get('save-please-login-partial'));
} else {
this.saveForm.submit(this.onSaveFormSubmit_.bind(this));
this.saveOnlineStatus.html(pskl.utils.Template.get('save-online-status-partial'));
}
this.saveLocalButton.click(this.onSaveLocalClick_.bind(this));
this.updateLocalStatusFilename_();
};
ns.SaveController.prototype.updateLocalStatusFilename_ = function () {
this.saveFileStatus.html(pskl.utils.Template.getAndReplace('save-file-status-template', {
name : this.getLocalFilename_()
}));
};
ns.SaveController.prototype.getLocalFilename_ = function () {
var piskelName = this.getName();
var timestamp = pskl.utils.DateUtils.format(this.timestamp, "{{Y}}{{M}}{{D}}-{{H}}{{m}}{{s}}");
return piskelName + "-" + timestamp + ".piskel";
};
ns.SaveController.prototype.onSaveFormSubmit_ = function (evt) {
evt.preventDefault();
evt.stopPropagation();
var name = this.getName();
var description = this.getDescription();
var isPublic = !!this.isPublicCheckbox.prop('checked');
if (pskl.app.isLoggedIn()) {
this.saveOnline_();
} else {
this.saveLocal_();
}
var descriptor = new pskl.model.piskel.Descriptor(name, description, isPublic);
this.piskelController.getPiskel().setDescriptor(descriptor);
this.beforeSaving_();
pskl.app.storageService.store({
success : this.onSaveSuccess_.bind(this),
error : this.onSaveError_.bind(this),
after : this.afterSaving_.bind(this)
});
};
ns.SaveController.prototype.onSaveLocalClick_ = function (evt) {
ns.SaveController.prototype.saveOnline_ = function () {
var name = this.getName();
if (!name) {
name = window.prompt('Please specify a name', 'New piskel');
}
if (name) {
var description = this.getDescription();
var isPublic = !!this.isPublicCheckbox.prop('checked');
var descriptor = new pskl.model.piskel.Descriptor(name, description, isPublic);
this.piskelController.getPiskel().setDescriptor(descriptor);
this.beforeSaving_();
this.saveOnlineButton.attr('disabled', true);
this.saveOnlineStatus.html('Saving ...');
pskl.app.storageService.store({
success : this.onSaveSuccess_.bind(this),
error : this.onSaveError_.bind(this),
after : this.afterOnlineSaving_.bind(this)
});
}
};
ns.SaveController.prototype.saveLocal_ = function () {
var localStorageService = pskl.app.localStorageService;
var isOk = true;
var name = this.getName();
@ -71,10 +118,19 @@
window.setTimeout(function () {
this.onSaveSuccess_();
this.afterSaving_();
}.bind(this), 1000);
}.bind(this), 500);
}
};
ns.SaveController.prototype.saveFile_ = function () {
this.beforeSaving_();
pskl.utils.BlobUtils.stringToBlob(pskl.app.piskelController.serialize(), function(blob) {
pskl.utils.FileUtils.downloadAsFile(blob, this.getLocalFilename_());
this.onSaveSuccess_();
this.afterSaving_();
}.bind(this), "application/piskel+json");
};
ns.SaveController.prototype.getName = function () {
return this.nameInput.val();
};
@ -84,14 +140,22 @@
};
ns.SaveController.prototype.beforeSaving_ = function () {
this.saveCloudButton.attr('disabled', true);
this.status.html('Saving ...');
this.updatePiskelDescriptor_();
if (this.piskelName) {
this.piskelName.classList.add('piskel-name-saving');
}
};
ns.SaveController.prototype.updatePiskelDescriptor_ = function () {
var name = this.getName();
var description = this.getDescription();
var isPublic = !!this.isPublicCheckbox.prop('checked');
var descriptor = new pskl.model.piskel.Descriptor(name, description, isPublic);
this.piskelController.getPiskel().setDescriptor(descriptor);
};
ns.SaveController.prototype.onSaveSuccess_ = function () {
$.publish(Events.CLOSE_SETTINGS_DRAWER);
$.publish(Events.SHOW_NOTIFICATION, [{"content": "Successfully saved !"}]);
@ -102,14 +166,17 @@
$.publish(Events.SHOW_NOTIFICATION, [{"content": "Saving failed ("+status+")"}]);
};
ns.SaveController.prototype.afterSaving_ = function () {
this.saveCloudButton.attr('disabled', false);
this.status.html('');
ns.SaveController.prototype.afterOnlineSaving_ = function () {
this.saveOnlineButton.attr('disabled', false);
this.saveOnlineStatus.html('');
this.afterSaving_();
};
ns.SaveController.prototype.afterSaving_ = function () {
if (this.piskelName) {
this.piskelName.classList.remove('piskel-name-saving');
}
window.setTimeout($.publish.bind($, Events.HIDE_NOTIFICATION), 2000);
window.setTimeout($.publish.bind($, Events.HIDE_NOTIFICATION), 5000);
};
})();

View File

@ -10,13 +10,9 @@
template : 'templates/settings/resize.html',
controller : ns.ResizeController
},
'gif' : {
template : 'templates/settings/export-gif.html',
controller : ns.GifExportController
},
'png' : {
template : 'templates/settings/export-png.html',
controller : ns.PngExportController
'export' : {
template : 'templates/settings/export.html',
controller : ns.ImageExportController
},
'import' : {
template : 'templates/settings/import.html',

View File

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

View File

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

View File

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

View File

@ -11,25 +11,42 @@
ns.Lighten = function() {
this.superclass.constructor.call(this);
this.toolId = "tool-lighten";
this.helpText = "Lighten (hold ctrl for Darken)";
this.resetUsedPixels_();
};
pskl.utils.inherit(ns.Lighten, ns.SimplePen);
this.helpText = "Lighten";
this.tooltipDescriptors = [
{key : 'ctrl', description : 'Darken'},
{key : 'shift', description : 'Apply only once per pixel'}
];
ns.Lighten.prototype.resetUsedPixels_ = function() {
this.usedPixels_ = {
darken : {},
lighten : {}
};
};
pskl.utils.inherit(ns.Lighten, ns.SimplePen);
/**
* @override
* @Override
*/
ns.Lighten.prototype.resetUsedPixels_ = function() {
this.usedPixels_ = {
darken : {},
lighten : {}
};
this.superclass.resetUsedPixels_.call(this);
};
/**
* @Override
*/
ns.Lighten.prototype.applyToolAt = function(col, row, color, frame, overlay, event, mouseButton) {
var pixelColor = frame.getPixel(col, row);
var overlayColor = overlay.getPixel(col, row);
var frameColor = frame.getPixel(col, row);
var pixelColor = overlayColor === Constants.TRANSPARENT_COLOR ? frameColor : overlayColor;
var isDarken = event.ctrlKey || event.cmdKey;
var isDarken = pskl.utils.UserAgent.isMac ? event.metaKey : event.ctrlKey;
var isSinglePass = event.shiftKey;
var isTransparent = pixelColor === Constants.TRANSPARENT_COLOR;
@ -38,7 +55,7 @@
var doNotModify = isTransparent || (isSinglePass && usedPixels[key]);
if (doNotModify) {
color = pixelColor;
color = window.tinycolor(pixelColor);
} else {
var step = isSinglePass ? DEFAULT_STEP * 2 : DEFAULT_STEP;
if (isDarken) {
@ -47,17 +64,10 @@
color = window.tinycolor.lighten(pixelColor, step);
}
}
if (color) {
usedPixels[key] = true;
this.superclass.applyToolAt.call(this, col, row, color.toRgbString(), frame, overlay, event);
}
};
ns.Lighten.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) {
this.resetUsedPixels_();
$.publish(Events.PISKEL_SAVE_STATE, {
type : pskl.service.HistoryService.SNAPSHOT
});
};
})();

View File

@ -30,16 +30,3 @@
pskl.PixelUtils.paintSimilarConnectedPixelsFromFrame(frame, replayData.col, replayData.row, replayData.color);
};
})();

View File

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

View File

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

View File

@ -22,12 +22,18 @@
* @override
*/
ns.SimplePen.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
frame.setPixel(col, row, color);
this.previousCol = col;
this.previousRow = row;
overlay.setPixel(col, row, color);
if (color === Constants.TRANSPARENT_COLOR) {
frame.setPixel(col, row, color);
}
this.pixels.push({
col : col,
row : row
row : row,
color : color
});
};
@ -55,17 +61,30 @@
ns.SimplePen.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) {
// apply on real frame
this.setPixelsToFrame_(frame, this.pixels);
// save state
this.raiseSaveStateEvent({
pixels : this.pixels.slice(0),
color : color
});
this.pixels = [];
// reset
this.resetUsedPixels_();
};
ns.SimplePen.prototype.replay = function (frame, replayData) {
var pixels = replayData.pixels;
this.setPixelsToFrame_(frame, replayData.pixels, replayData.color);
};
ns.SimplePen.prototype.setPixelsToFrame_ = function (frame, pixels, color) {
pixels.forEach(function (pixel) {
frame.setPixel(pixel.col, pixel.row, replayData.color);
frame.setPixel(pixel.col, pixel.row, pixel.color);
});
};
ns.SimplePen.prototype.resetUsedPixels_ = function() {
this.pixels = [];
};
})();

View File

@ -5,22 +5,24 @@
this.superclass.constructor.call(this);
this.toolId = "tool-vertical-mirror-pen";
this.helpText = "vertical mirror pen tool";
this.helpText = "Vertical Mirror pen";
this.swap = null;
this.tooltipDescriptors = [
{key : 'ctrl', description : 'Use horizontal axis'},
{key : 'shift', description : 'Use horizontal and vertical axis'}
];
};
pskl.utils.inherit(ns.VerticalMirrorPen, ns.SimplePen);
ns.VerticalMirrorPen.prototype.setMirrorContext = function() {
this.swap = this.previousCol;
this.previousCol = this.mirroredPreviousCol;
ns.VerticalMirrorPen.prototype.backupPreviousPositions_ = function () {
this.backupPreviousCol = this.previousCol;
this.backupPreviousRow = this.previousRow;
};
ns.VerticalMirrorPen.prototype.unsetMirrorContext = function() {
this.mirroredPreviousCol = this.previousCol;
this.previousCol = this.swap;
ns.VerticalMirrorPen.prototype.restorePreviousPositions_ = function () {
this.previousCol = this.backupPreviousCol;
this.previousRow = this.backupPreviousRow;
};
/**
@ -28,19 +30,33 @@
*/
ns.VerticalMirrorPen.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
this.superclass.applyToolAt.call(this, col, row, color, frame, overlay);
this.backupPreviousPositions_();
var mirroredCol = this.getSymmetricCol_(col, frame);
this.mirroredPreviousCol = mirroredCol;
var mirroredRow = this.getSymmetricRow_(row, frame);
this.setMirrorContext();
this.superclass.applyToolAt.call(this, mirroredCol, row, color, frame, overlay);
this.unsetMirrorContext();
var hasCtrlKey = pskl.utils.UserAgent.isMac ? event.metaKey : event.ctrlKey;
if (!hasCtrlKey) {
this.superclass.applyToolAt.call(this, mirroredCol, row, color, frame, overlay);
}
if (event.shiftKey || hasCtrlKey) {
this.superclass.applyToolAt.call(this, col, mirroredRow, color, frame, overlay);
}
if (event.shiftKey) {
this.superclass.applyToolAt.call(this, mirroredCol, mirroredRow, color, frame, overlay);
}
this.restorePreviousPositions_();
};
/**
* @private
*/
ns.VerticalMirrorPen.prototype.getSymmetricCol_ = function(col, frame) {
return frame.getWidth() - col - 1;
};
ns.VerticalMirrorPen.prototype.getSymmetricRow_ = function(row, frame) {
return frame.getHeight() - row - 1;
};
})();

View File

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

View File

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

View File

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

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

View File

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

View File

@ -96,4 +96,10 @@
ns.Layer.prototype.length = function () {
return this.frames.length;
};
ns.Layer.prototype.getHash = function () {
return this.frames.map(function (frame) {
return frame.getHash();
}).join('-');
};
})();

View File

@ -109,4 +109,10 @@
var appEngineEditorHeader = $('.piskel-name').html(this.descriptor.name);
};
ns.Piskel.prototype.getHash = function () {
return this.layers.map(function (layer) {
return layer.getHash();
}).join('-');
};
})();

View File

@ -0,0 +1,79 @@
(function () {
var ns = $.namespace('pskl.model.frame');
var DEFAULT_CLEAR_INTERVAL = 10 * 60 *1000;
var DEFAULT_FRAME_PROCESSOR = function (frame) {
return pskl.utils.FrameUtils.toImage(frame);
};
var DEFAULT_OUTPUT_CLONER = function (o) {return o;};
var DEFAULT_NAMESPACE = '__cache_default__';
ns.CachedFrameProcessor = function (cacheResetInterval) {
this.cache_ = {};
this.cacheResetInterval = cacheResetInterval || DEFAULT_CLEAR_INTERVAL;
this.frameProcessor = DEFAULT_FRAME_PROCESSOR;
this.outputCloner = DEFAULT_OUTPUT_CLONER;
window.setInterval(this.clear.bind(this), this.cacheResetInterval);
};
ns.CachedFrameProcessor.prototype.clear = function () {
this.cache_ = {};
};
/**
* Set the processor function that will be called when there is a cache miss
* Function with 1 argument : pskl.model.Frame
* @param {Function} frameProcessor
*/
ns.CachedFrameProcessor.prototype.setFrameProcessor = function (frameProcessor) {
this.frameProcessor = frameProcessor;
};
/**
* Set the cloner that will be called when there is a miss on the 1st level cache
* but a hit on the 2nd level cache.
* Function with 2 arguments : cached value, frame
* @param {Function} outputCloner
*/
ns.CachedFrameProcessor.prototype.setOutputCloner = function (outputCloner) {
this.outputCloner = outputCloner;
};
/**
* Retrieve the processed frame from the cache, in the (optional) namespace
* If the first level cache is empty, attempt to clone it from 2nd level cache. If second level cache is empty process the frame.
* @param {pskl.model.Frame} frame
* @param {String} namespace
* @return {Object} the processed frame
*/
ns.CachedFrameProcessor.prototype.get = function (frame, namespace) {
var processedFrame = null;
namespace = namespace || DEFAULT_NAMESPACE;
if (!this.cache_[namespace]) {
this.cache_[namespace] = {};
}
var cache = this.cache_[namespace];
var cacheKey = frame.getHash();
if (cache[cacheKey]) {
processedFrame = cache[cacheKey];
} else {
var frameAsString = JSON.stringify(frame.getPixels());
if (cache[frameAsString]) {
processedFrame = this.outputCloner(cache[frameAsString], frame);
} else {
processedFrame = this.frameProcessor(frame);
cache[frameAsString] = processedFrame;
}
cache[cacheKey] = processedFrame;
}
return processedFrame;
};
})();

View File

@ -8,11 +8,19 @@
this.displayContainer = document.createElement('div');
this.displayContainer.classList.add('tiled-frame-container');
container.get(0).appendChild(this.displayContainer);
this.cachedFrameProcessor = new pskl.model.frame.CachedFrameProcessor();
this.cachedFrameProcessor.setFrameProcessor(this.frameToDataUrl_.bind(this));
};
ns.TiledFrameRenderer.prototype.frameToDataUrl_ = function (frame) {
var canvas = new pskl.utils.FrameUtils.toImage(frame, this.zoom);
return canvas.toDataURL('image/png');
};
ns.TiledFrameRenderer.prototype.render = function (frame) {
var canvas = new pskl.utils.FrameUtils.toImage(frame, this.zoom);
this.displayContainer.style.backgroundImage = 'url(' + canvas.toDataURL('image/png') + ')';
var imageSrc = this.cachedFrameProcessor.get(frame, this.zoom);
this.displayContainer.style.backgroundImage = 'url(' + imageSrc + ')';
};
ns.TiledFrameRenderer.prototype.show = function () {

View File

@ -14,6 +14,8 @@
this.add(this.aboveRenderer);
this.serializedRendering = '';
$.subscribe(Events.PISKEL_RESET, this.flush.bind(this));
};
pskl.utils.inherit(pskl.rendering.layer.LayersRenderer, pskl.rendering.CompositeRenderer);
@ -25,6 +27,10 @@
var currentFrameIndex = this.piskelController.getCurrentFrameIndex();
var currentLayerIndex = this.piskelController.getCurrentLayerIndex();
var downLayers = layers.slice(0, currentLayerIndex);
var upLayers = layers.slice(currentLayerIndex + 1, layers.length);
var serializedRendering = [
this.getZoom(),
this.getGridWidth(),
@ -32,8 +38,8 @@
offset.y,
size.width,
size.height,
currentFrameIndex,
currentLayerIndex,
this.getHashForLayersAt_(currentFrameIndex, downLayers),
this.getHashForLayersAt_(currentFrameIndex, upLayers),
layers.length
].join("-");
@ -43,18 +49,15 @@
this.clear();
var downLayers = layers.slice(0, currentLayerIndex);
if (downLayers.length > 0) {
var downFrame = this.getFrameForLayersAt_(currentFrameIndex, downLayers);
this.belowRenderer.render(downFrame);
}
var upLayers = layers.slice(currentLayerIndex + 1, layers.length);
if (upLayers.length > 0) {
var upFrame = this.getFrameForLayersAt_(currentFrameIndex, upLayers);
this.aboveRenderer.render(upFrame);
}
}
};
@ -78,6 +81,13 @@
return pskl.utils.FrameUtils.merge(frames);
};
ns.LayersRenderer.prototype.getHashForLayersAt_ = function (frameIndex, layers) {
var hash = layers.map(function (l) {
return l.getFrameAt(frameIndex).getHash();
});
return hash.join('-');
};
ns.LayersRenderer.prototype.flush = function () {
this.serializedRendering = '';
};

View File

@ -19,7 +19,6 @@
$.subscribe(Events.SELECTION_MOVE_REQUEST, $.proxy(this.onSelectionMoved_, this));
pskl.app.shortcutService.addShortcut('ctrl+V', this.paste.bind(this));
pskl.app.shortcutService.addShortcut('ctrl+shift+V', this.pasteOpaqueOnly.bind(this));
pskl.app.shortcutService.addShortcut('ctrl+X', this.cut.bind(this));
pskl.app.shortcutService.addShortcut('ctrl+C', this.copy.bind(this));
pskl.app.shortcutService.addShortcut('del', this.erase.bind(this));
@ -92,13 +91,6 @@
};
ns.SelectionManager.prototype.paste = function() {
if(this.currentSelection && this.currentSelection.hasPastedContent) {
var pixels = this.currentSelection.pixels;
this.pastePixels(pixels);
}
};
ns.SelectionManager.prototype.pasteOpaqueOnly = function() {
if(this.currentSelection && this.currentSelection.hasPastedContent) {
var pixels = this.currentSelection.pixels;
var opaquePixels = pixels.filter(function (p) {
@ -111,6 +103,10 @@
ns.SelectionManager.prototype.pastePixels = function(pixels) {
var currentFrame = this.piskelController.getCurrentFrame();
pixels.forEach(function (pixel) {
currentFrame.setPixel(pixel.col,pixel.row,pixel.color);
});
$.publish(Events.PISKEL_SAVE_STATE, {
type : pskl.service.HistoryService.REPLAY,
scope : this,
@ -119,10 +115,6 @@
pixels : JSON.parse(JSON.stringify(pixels.slice(0)))
}
});
pixels.forEach(function (pixel) {
currentFrame.setPixel(pixel.col,pixel.row,pixel.color);
});
};
ns.SelectionManager.prototype.replay = function (frame, replayData) {

View File

@ -0,0 +1,61 @@
(function () {
var ns = $.namespace('pskl.service');
var BACKUP_INTERVAL = 1000 * 60;
ns.BackupService = function (piskelController) {
this.piskelController = piskelController;
this.lastHash = null;
};
ns.BackupService.prototype.init = function () {
var previousPiskel = window.localStorage.getItem('bkp.next.piskel');
var previousInfo = window.localStorage.getItem('bkp.next.info');
if (previousPiskel && previousInfo) {
window.localStorage.setItem('bkp.prev.piskel', previousPiskel);
window.localStorage.setItem('bkp.prev.info', previousInfo);
}
window.setInterval(this.backup.bind(this), BACKUP_INTERVAL);
};
ns.BackupService.prototype.backup = function () {
var piskel = this.piskelController.getPiskel();
var descriptor = piskel.getDescriptor();
var hash = piskel.getHash();
var info = {
name : descriptor.name,
description : descriptor.info,
fps : this.piskelController.getFPS(),
date : Date.now(),
hash : hash
};
// Do not save an unchanged piskel
if (hash !== this.lastHash) {
this.lastHash = hash;
window.localStorage.setItem('bkp.next.piskel', this.piskelController.serialize());
window.localStorage.setItem('bkp.next.info', JSON.stringify(info));
}
};
ns.BackupService.prototype.getPreviousPiskelInfo = function () {
var previousInfo = window.localStorage.getItem('bkp.prev.info');
if (previousInfo) {
return JSON.parse(previousInfo);
}
};
ns.BackupService.prototype.load = function() {
var previousPiskel = window.localStorage.getItem('bkp.prev.piskel');
var previousInfo = window.localStorage.getItem('bkp.prev.info');
previousPiskel = JSON.parse(previousPiskel);
previousInfo = JSON.parse(previousInfo);
pskl.utils.serialization.Deserializer.deserialize(previousPiskel, function (piskel) {
piskel.setDescriptor(new pskl.model.piskel.Descriptor(previousInfo.name, previousInfo.description, true));
pskl.app.piskelController.setPiskel(piskel);
pskl.app.animationController.setFPS(previousInfo.fps);
});
};
})();

View File

@ -0,0 +1,23 @@
(function () {
var ns = $.namespace('pskl.service');
ns.BeforeUnloadService = function (piskelController) {
this.piskelController = piskelController;
};
ns.BeforeUnloadService.prototype.init = function () {
window.addEventListener("beforeunload", this.onBeforeUnload.bind(this));
};
ns.BeforeUnloadService.prototype.onBeforeUnload = function (evt) {
pskl.app.backupService.backup();
if (pskl.app.savedStatusService.isDirty()) {
var confirmationMessage = "Your Piskel seems to have unsaved changes";
(evt || window.event).returnValue = confirmationMessage;
return confirmationMessage;
}
};
})();

View File

@ -4,6 +4,9 @@
ns.CurrentColorsService = function (piskelController) {
this.piskelController = piskelController;
this.currentColors = [];
this.cachedFrameProcessor = new pskl.model.frame.CachedFrameProcessor();
this.cachedFrameProcessor.setFrameProcessor(this.frameToColors_.bind(this));
this.framesColorsCache_ = {};
};
@ -16,33 +19,35 @@
return this.currentColors;
};
ns.CurrentColorsService.prototype.frameToColors_ = function (frame) {
var frameColors = {};
frame.forEachPixel(function (color, x, y) {
frameColors[color] = (frameColors[color] || 0) + 1;
});
return frameColors;
};
ns.CurrentColorsService.prototype.onPiskelUpdated_ = function (evt) {
var layers = this.piskelController.getLayers();
var frames = layers.map(function (l) {return l.getFrames();}).reduce(function (p, n) {return p.concat(n);});
var colors = {};
frames.forEach(function (f) {
var frameHash = f.getHash();
if (!this.framesColorsCache_[frameHash]) {
var frameColors = {};
f.forEachPixel(function (color, x, y) {
frameColors[color] = true;
});
this.framesColorsCache_[frameHash] = frameColors;
}
Object.keys(this.framesColorsCache_[frameHash]).forEach(function (color) {
colors[color] = true;
var frameColors = this.cachedFrameProcessor.get(f);
Object.keys(frameColors).slice(0, Constants.MAX_CURRENT_COLORS_DISPLAYED).forEach(function (color) {
colors[color] = (colors[color] || 0) + frameColors[color];
});
}.bind(this));
// Remove transparent color from used colors
delete colors[Constants.TRANSPARENT_COLOR];
this.currentColors = Object.keys(colors);
// limit the array to the max colors to display
this.currentColors = Object.keys(colors).slice(0, Constants.MAX_CURRENT_COLORS_DISPLAYED);
// sort by most frequent color
this.currentColors = this.currentColors.sort(function (c1, c2) {
if (c1 < c2) {
return -1;
} else if (c1 > c2) {
return 1;
} else {
return 0;
}
return colors[c2] - colors[c1];
});
// TODO : only fire if there was a change

View File

@ -0,0 +1,103 @@
(function () {
var ns = $.namespace('pskl.service');
ns.FileDropperService = function (piskelController, drawingAreaContainer) {
this.piskelController = piskelController;
this.drawingAreaContainer = drawingAreaContainer;
this.dropPosition_ = null;
};
ns.FileDropperService.prototype.init = function () {
document.body.addEventListener('drop', this.onFileDrop.bind(this), false);
document.body.addEventListener('dragover', this.onFileDragOver.bind(this), false);
};
ns.FileDropperService.prototype.onFileDragOver = function (event) {
event.stopPropagation();
event.preventDefault();
event.dataTransfer.dropEffect = 'copy';
};
ns.FileDropperService.prototype.onFileDrop = function (event) {
event.preventDefault();
event.stopPropagation();
this.dropPosition_ = {
x : event.clientX,
y : event.clientY
};
var files = event.dataTransfer.files;
for (var i = 0; i < files.length ; i++) {
var file = files[i];
var isImage = file.type.indexOf('image') === 0;
if (isImage) {
this.readImageFile_(file);
} else if (/\.piskel$/i.test(file.name)) {
pskl.utils.PiskelFileUtils.loadFromFile(file, this.onPiskelFileLoaded_);
}
}
};
ns.FileDropperService.prototype.onPiskelFileLoaded_ = function (piskel, descriptor, fps) {
if (window.confirm('This will replace your current animation')) {
piskel.setDescriptor(descriptor);
pskl.app.piskelController.setPiskel(piskel);
pskl.app.animationController.setFPS(fps);
}
};
ns.FileDropperService.prototype.readImageFile_ = function (imageFile) {
pskl.utils.FileUtils.readFile(imageFile, this.processImageSource_.bind(this));
};
ns.FileDropperService.prototype.processImageSource_ = function (imageSource) {
this.importedImage_ = new Image();
this.importedImage_.onload = this.onImageLoaded_.bind(this);
this.importedImage_.src = imageSource;
};
ns.FileDropperService.prototype.onImageLoaded_ = function () {
var droppedFrame = pskl.utils.FrameUtils.createFromImage(this.importedImage_);
var currentFrame = this.piskelController.getCurrentFrame();
var dropCoordinates = this.adjustDropPosition_(this.dropPosition_, droppedFrame);
currentFrame.forEachPixel(function (color, x, y) {
var fColor = droppedFrame.getPixel(x-dropCoordinates.x, y-dropCoordinates.y);
if (fColor && fColor != Constants.TRANSPARENT_COLOR) {
currentFrame.setPixel(x, y, fColor);
}
});
$.publish(Events.PISKEL_RESET);
$.publish(Events.PISKEL_SAVE_STATE, {
type : pskl.service.HistoryService.SNAPSHOT
});
};
ns.FileDropperService.prototype.adjustDropPosition_ = function (position, droppedFrame) {
var framePosition = pskl.app.drawingController.getSpriteCoordinates(position.x, position.y);
var xCoord = framePosition.x - Math.floor(droppedFrame.width/2);
var yCoord = framePosition.y - Math.floor(droppedFrame.height/2);
xCoord = Math.max(0, xCoord);
yCoord = Math.max(0, yCoord);
var currentFrame = this.piskelController.getCurrentFrame();
if (droppedFrame.width <= currentFrame.width) {
xCoord = Math.min(xCoord, currentFrame.width - droppedFrame.width);
}
if (droppedFrame.height <= currentFrame.height) {
yCoord = Math.min(yCoord, currentFrame.height - droppedFrame.height);
}
return {
x : xCoord,
y : yCoord
};
};
})();

View File

@ -11,10 +11,17 @@
this.saveState__b = this.onSaveStateEvent.bind(this);
this.lastLoadState = -1;
this.saveNextAsSnapshot = false;
};
ns.HistoryService.SNAPSHOT = 'SNAPSHOT';
ns.HistoryService.REPLAY = 'REPLAY';
/**
* This event alters the state (frames, layers) of the piskel. The event is triggered before the execution of associated command.
* Don't store snapshots for such events.
*/
ns.HistoryService.REPLAY_NO_SNAPSHOT = 'REPLAY_NO_SNAPSHOT';
ns.HistoryService.prototype.init = function () {
$.subscribe(Events.PISKEL_SAVE_STATE, this.saveState__b);
@ -41,8 +48,18 @@
layerIndex : this.piskelController.currentLayerIndex
};
if (stateInfo.type === ns.HistoryService.SNAPSHOT || this.currentIndex % SNAPSHOT_PERIOD === 0) {
var isSnapshot = stateInfo.type === ns.HistoryService.SNAPSHOT;
var isNoSnapshot = stateInfo.type === ns.HistoryService.REPLAY_NO_SNAPSHOT;
var isAtAutoSnapshotInterval = this.currentIndex % SNAPSHOT_PERIOD === 0 || this.saveNextAsSnapshot;
if (isNoSnapshot && isAtAutoSnapshotInterval) {
this.saveNextAsSnapshot = true;
} else if (isSnapshot || isAtAutoSnapshotInterval) {
state.piskel = this.piskelController.serialize(true);
this.saveNextAsSnapshot = false;
}
if (isSnapshot) {
}
this.stateQueue.push(state);
@ -70,17 +87,28 @@
};
ns.HistoryService.prototype.loadState = function (index) {
if (this.isLoadStateAllowed_(index)) {
this.lastLoadState = Date.now();
try {
if (this.isLoadStateAllowed_(index)) {
this.lastLoadState = Date.now();
var snapshotIndex = this.getPreviousSnapshotIndex_(index);
if (snapshotIndex < 0) {
throw 'Could not find previous SNAPSHOT saved in history stateQueue';
var snapshotIndex = this.getPreviousSnapshotIndex_(index);
if (snapshotIndex < 0) {
throw 'Could not find previous SNAPSHOT saved in history stateQueue';
}
var serializedPiskel = this.getSnapshotFromState_(snapshotIndex);
var onPiskelLoadedCb = this.onPiskelLoaded_.bind(this, index, snapshotIndex);
pskl.utils.serialization.Deserializer.deserialize(serializedPiskel, onPiskelLoadedCb);
}
var serializedPiskel = this.getSnapshotFromState_(snapshotIndex);
var onPiskelLoadedCb = this.onPiskelLoaded_.bind(this, index, snapshotIndex);
pskl.utils.serialization.Deserializer.deserialize(serializedPiskel, onPiskelLoadedCb);
} catch (e) {
window.console.error("[CRITICAL ERROR] : Unable to load a history state.");
if (typeof e === "string") {
window.console.error(e);
} else {
window.console.error(e.message);
window.console.error(e.stack);
}
this.stateQueue = [];
this.currentIndex = -1;
}
};
@ -114,6 +142,7 @@
if (lastState) {
this.setupState(lastState);
}
this.currentIndex = index;
$.publish(Events.PISKEL_RESET);
if (originalSize !== this.getPiskelSize_()) {

View File

@ -11,8 +11,6 @@
ns.LocalStorageService.prototype.init = function() {};
// localStorage.setItem('piskel_bkp', pskl.app.piskelController.serialize())
ns.LocalStorageService.prototype.save = function(name, description, piskel) {
this.removeFromKeys_(name);
this.addToKeys_(name, description, Date.now());
@ -22,10 +20,16 @@
ns.LocalStorageService.prototype.load = function(name) {
var piskelString = this.getPiskel(name);
var key = this.getKey_(name);
var serializedPiskel = JSON.parse(piskelString);
// FIXME : should be moved to deserializer
// Deserializer should call callback with descriptor + fps information
var fps = serializedPiskel.piskel.fps;
var description = serializedPiskel.piskel.description;
pskl.utils.serialization.Deserializer.deserialize(JSON.parse(piskelString), function (piskel) {
piskel.setDescriptor(new pskl.model.piskel.Descriptor(name, key.description, true));
pskl.utils.serialization.Deserializer.deserialize(serializedPiskel, function (piskel) {
piskel.setDescriptor(new pskl.model.piskel.Descriptor(name, description, true));
pskl.app.piskelController.setPiskel(piskel);
pskl.app.animationController.setFPS(fps);
});
};

View File

@ -10,8 +10,6 @@
$.subscribe(Events.PISKEL_RESET, this.onPiskelReset.bind(this));
$.subscribe(Events.PISKEL_SAVED, this.onPiskelSaved.bind(this));
window.addEventListener("beforeunload", this.onBeforeUnload.bind(this));
};
ns.SavedStatusService.prototype.onPiskelReset = function () {
@ -52,13 +50,8 @@
}
};
ns.SavedStatusService.prototype.onBeforeUnload = function (evt) {
ns.SavedStatusService.prototype.isDirty = function (evt) {
var piskel = this.piskelController.getPiskel();
if (piskel.isDirty_) {
var confirmationMessage = "Your Piskel seems to have unsaved changes";
(evt || window.event).returnValue = confirmationMessage;
return confirmationMessage;
}
return piskel.isDirty_;
};
})();

View File

@ -55,6 +55,9 @@
};
ns.CheatsheetService.prototype.toDescriptor_ = function (shortcut, description, icon) {
if (pskl.utils.UserAgent.isMac) {
shortcut = shortcut.replace('ctrl', 'cmd');
}
return {
'shortcut' : shortcut,
'description' : description,
@ -84,7 +87,7 @@
ns.CheatsheetService.prototype.initMarkupForTools_ = function () {
var descriptors = pskl.app.toolController.tools.map(function (tool) {
return this.toDescriptor_(tool.shortcut, tool.instance.helpText, 'tool-icon ' + tool.instance.toolId);
return this.toDescriptor_(tool.shortcut, tool.instance.getHelpText(), 'tool-icon ' + tool.instance.toolId);
}.bind(this));
this.initMarkupAbstract_(descriptors, '.cheatsheet-tool-shortcuts');
@ -103,7 +106,9 @@
this.toDescriptor_('N', 'Create new frame'),
this.toDescriptor_('shift + N', 'Duplicate selected frame'),
this.toDescriptor_('shift + ?', 'Open/Close this popup'),
this.toDescriptor_('alt + P', 'Open the Palette Manager')
this.toDescriptor_('alt + P', 'Open the Palette Manager'),
this.toDescriptor_('alt + O', 'Toggle Onion Skin'),
this.toDescriptor_('alt + L', 'Toggle Layer Preview')
];
this.initMarkupAbstract_(descriptors, '.cheatsheet-misc-shortcuts');

View File

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

43
src/js/snippets.js Normal file
View File

@ -0,0 +1,43 @@
(function () {
var flipFrame = function (frame, horizontal, vertical) {
var clone = frame.clone();
var w = frame.getWidth();
var h = frame.getHeight();
clone.forEachPixel(function (color, x, y) {
if (horizontal) {
x = w-x-1;
}
if (vertical) {
y = h-y-1;
}
frame.pixels[x][y] = color;
});
frame.version++;
};
window.flip = function (horizontal, vertical) {
var currentFrameIndex = pskl.app.piskelController.getCurrentFrameIndex();
var layers = pskl.app.piskelController.getLayers();
layers.forEach(function (layer) {
flipFrame(layer.getFrameAt(currentFrameIndex), horizontal, vertical);
});
$.publish(Events.PISKEL_RESET);
$.publish(Events.PISKEL_SAVE_STATE, {
type : pskl.service.HistoryService.SNAPSHOT
});
};
window.copyToAll = function () {
var ref = pskl.app.piskelController.getCurrentFrame();
var layer = pskl.app.piskelController.getCurrentLayer();
layer.getFrames().forEach(function (frame) {
if (frame !== ref) {
frame.setPixels(ref.getPixels());
}
});
$.publish(Events.PISKEL_RESET);
$.publish(Events.PISKEL_SAVE_STATE, {
type : pskl.service.HistoryService.SNAPSHOT
});
};
})();

View File

@ -3,8 +3,8 @@
var BASE64_REGEX = /\s*;\s*base64\s*(?:;|$)/i;
ns.ImageToBlob = {
imageDataToBlob : function(dataURI, type, callback) {
ns.BlobUtils = {
dataToBlob : function(dataURI, type, callback) {
var header_end = dataURI.indexOf(","),
data = dataURI.substring(header_end + 1),
isBase64 = BASE64_REGEX.test(dataURI.substring(0, header_end)),
@ -26,13 +26,18 @@
canvasToBlob : function(canvas, callback, type /*, ...args*/) {
type = type || "image/png";
if (this.mozGetAsFile) {
callback(this.mozGetAsFile("canvas", type));
if (canvas.mozGetAsFile) {
callback(canvas.mozGetAsFile("canvas", type));
} else {
var args = Array.prototype.slice.call(arguments, 2);
var dataURI = canvas.toDataURL.apply(canvas, args);
pskl.utils.ImageToBlob.imageDataToBlob(dataURI, type, callback);
pskl.utils.BlobUtils.dataToBlob(dataURI, type, callback);
}
},
stringToBlob : function (string, callback, type) {
type = type || "text/plain";
pskl.utils.BlobUtils.dataToBlob('data:'+type+',' + string, type, callback);
}
};
})();

View File

@ -48,6 +48,16 @@
}
},
clone : function (canvas) {
var clone = pskl.CanvasUtils.createCanvas(canvas.width, canvas.height);
//apply the old canvas to the new one
clone.getContext('2d').drawImage(canvas, 0, 0);
//return the new canvas
return clone;
},
getImageDataFromCanvas : function (canvas) {
var sourceContext = canvas.getContext('2d');
return sourceContext.getImageData(0, 0, canvas.width, canvas.height).data;

25
src/js/utils/DateUtils.js Normal file
View File

@ -0,0 +1,25 @@
(function () {
var ns = $.namespace('pskl.utils');
var pad = function (num) {
if (num < 10) {
return "0" + num;
} else {
return "" + num;
}
};
ns.DateUtils = {
format : function (date, format) {
date = new Date(date);
return pskl.utils.Template.replace(format, {
Y : date.getFullYear(),
M : pad(date.getMonth() + 1),
D : pad(date.getDate()),
H : pad(date.getHours()),
m : pad(date.getMinutes()),
s : pad(date.getSeconds())
});
}
};
})();

View File

@ -1,6 +1,10 @@
(function () {
var ns = $.namespace('pskl.utils');
var stopPropagation = function (e) {
e.stopPropagation();
};
ns.FileUtils = {
readFile : function (file, callback) {
var reader = new FileReader();
@ -10,7 +14,7 @@
reader.readAsDataURL(file);
},
downloadAsFile : function (filename, content) {
downloadAsFile : function (content, filename) {
var saveAs = window.saveAs || (navigator.msSaveBlob && navigator.msSaveBlob.bind(navigator));
if (saveAs) {
saveAs(content, filename);
@ -20,7 +24,9 @@
downloadLink.setAttribute('href', content);
downloadLink.setAttribute('download', filename);
document.body.appendChild(downloadLink);
downloadLink.addEventListener('click', stopPropagation);
downloadLink.click();
downloadLink.removeEventListener('click', stopPropagation);
document.body.removeChild(downloadLink);
}
}

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