Compare commits
56 Commits
Author | SHA1 | Date | |
---|---|---|---|
280dd1a809 | |||
c1900a07f0 | |||
a43b20e182 | |||
b556143b66 | |||
19c99d1aa7 | |||
dc78c3cecd | |||
829bcb8ad1 | |||
56f008bda6 | |||
5350255eee | |||
d4884a2de5 | |||
581bd46dcd | |||
1e8315f32c | |||
cc8460cc26 | |||
aa375315a2 | |||
e5cb0717e2 | |||
6af04bb599 | |||
dfc3bfd181 | |||
ad3dd935e0 | |||
18ff6f88a7 | |||
b2fbe269d3 | |||
a8ce829e6c | |||
2fabf68282 | |||
b66d5ee93b | |||
982a5ab048 | |||
a6d70920e2 | |||
b311312260 | |||
665d2bd9bc | |||
4aac65fb9e | |||
4102e929f4 | |||
b3bb2472f1 | |||
a6d939cc9a | |||
304a5c06da | |||
707a69182f | |||
8f5ead43d9 | |||
41a4ee3f3d | |||
f8b6d7b0d3 | |||
84e757768e | |||
264e236473 | |||
96fc5f2418 | |||
26a463c4b4 | |||
8e425c64d4 | |||
bf9be5de2d | |||
2c235e659b | |||
a77168986a | |||
24186d5aec | |||
7b3f5ee858 | |||
939042a645 | |||
fa4e96e7e5 | |||
fa626532ba | |||
a2e2459169 | |||
8a70943b09 | |||
d126023c4a | |||
f2281d7125 | |||
3efa94dce5 | |||
bd7ebc5f7d | |||
89466d582a |
1
.gitignore
vendored
@ -18,6 +18,7 @@ diff.txt
|
||||
|
||||
# build destination
|
||||
dest
|
||||
build/closure/closure_compiled_binary.js
|
||||
|
||||
# marked as private
|
||||
*.private.*
|
63
Gruntfile.js
@ -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
@ -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 |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
99
misc/icons/SVG/onion.svg
Normal 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 |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
72
misc/icons/SVG/swap-colors-sq.svg
Normal 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 |
97
misc/icons/SVG/swap-colors.svg
Normal 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 |
BIN
misc/icons/swap-colors-tests/swap-colors-square.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
misc/icons/swap-colors-tests/swap-colors-twirl-2.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
misc/icons/swap-colors-tests/swap-colors-twirl-3.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
misc/icons/swap-colors-tests/swap-colors-twirl.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
misc/icons/swap-colors-tests/swap.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
21
misc/scripts/copy-to-piskel-website.cmd
Normal 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
|
47
misc/selenium-ide/change-colors.html
Normal 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>
|
52
misc/selenium-ide/change-size.html
Normal 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>
|
82
misc/selenium-ide/select-tools.html
Normal 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>
|
92
misc/selenium-ide/user-preferences.html
Normal 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="1"]</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="2"]</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="3"]</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="4"]</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
</tbody></table>
|
||||
</body>
|
||||
</html>
|
@ -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",
|
||||
|
38
src/css/dialogs-browse-local.css
Normal 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;
|
||||
}
|
55
src/css/dialogs-import-image.css
Normal 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;
|
||||
}
|
@ -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
@ -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
13
src/css/fonts/piskel.svg
Normal 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=" " d="" horiz-adv-x="256" />
|
||||
<glyph unicode="" 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="" 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="" 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
BIN
src/css/fonts/piskel.woff
Normal file
@ -96,6 +96,10 @@
|
||||
border: #999 3px solid;
|
||||
}
|
||||
|
||||
.tile-view {
|
||||
position : relative;
|
||||
}
|
||||
|
||||
.preview-tile .tile-overlay {
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
|
@ -33,4 +33,8 @@ ul, li {
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: rgba(50, 50, 50, 0.4);
|
||||
}
|
||||
|
||||
a, a:visited {
|
||||
color:gold;
|
||||
}
|
@ -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
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
76
src/css/toolbox-animated-preview.css
Normal 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;
|
||||
}
|
@ -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 {
|
||||
|
@ -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
After Width: | Height: | Size: 734 B |
BIN
src/img/tools/swap-colors.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
@ -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>
|
||||
|
@ -11,6 +11,8 @@ var Constants = {
|
||||
MAX_HEIGHT : 1024,
|
||||
MAX_WIDTH : 1024,
|
||||
|
||||
MAX_CURRENT_COLORS_DISPLAYED : 100,
|
||||
|
||||
MINIMUM_ZOOM : 1,
|
||||
|
||||
PREVIEW_FILM_SIZE : 96,
|
||||
|
@ -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 @@
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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;
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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));
|
||||
|
18
src/js/controller/dialogs/AbstractDialogController.js
Normal 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);
|
||||
};
|
||||
|
||||
})();
|
57
src/js/controller/dialogs/BrowseLocalController.js
Normal 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;
|
||||
};
|
||||
})();
|
@ -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_();
|
||||
|
154
src/js/controller/dialogs/ImportImageController.js
Normal 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);
|
||||
};
|
||||
})();
|
@ -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();
|
||||
};
|
||||
|
@ -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)) {
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
};
|
||||
|
14
src/js/controller/settings/ImageExportController.js
Normal 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();
|
||||
};
|
||||
})();
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
};
|
||||
|
||||
})();
|
@ -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) {
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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',
|
||||
|
@ -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
|
||||
|
@ -10,6 +10,7 @@
|
||||
ns.ShapeTool.call(this);
|
||||
|
||||
this.toolId = "tool-circle";
|
||||
|
||||
this.helpText = "Circle tool";
|
||||
};
|
||||
|
||||
|
58
src/js/drawingtools/ColorSwap.js
Normal 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++;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
})();
|
@ -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
|
||||
});
|
||||
};
|
||||
})();
|
@ -30,16 +30,3 @@
|
||||
pskl.PixelUtils.paintSimilarConnectedPixelsFromFrame(frame, replayData.col, replayData.row, replayData.color);
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 = [];
|
||||
};
|
||||
})();
|
||||
|
@ -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;
|
||||
};
|
||||
})();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
};
|
||||
|
1
src/js/lib/gif/gif.ie.worker.js
Normal 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
@ -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();
|
||||
};
|
||||
|
@ -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('-');
|
||||
};
|
||||
})();
|
@ -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('-');
|
||||
};
|
||||
|
||||
})();
|
79
src/js/model/frame/CachedFrameProcessor.js
Normal 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;
|
||||
};
|
||||
})();
|
@ -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 () {
|
||||
|
@ -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 = '';
|
||||
};
|
||||
|
@ -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) {
|
||||
|
61
src/js/service/BackupService.js
Normal 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);
|
||||
});
|
||||
};
|
||||
})();
|
23
src/js/service/BeforeUnloadService.js
Normal 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;
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
@ -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
|
||||
|
103
src/js/service/FileDropperService.js
Normal 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
|
||||
};
|
||||
};
|
||||
|
||||
})();
|
@ -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_()) {
|
||||
|
@ -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);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -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_;
|
||||
};
|
||||
})();
|
@ -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');
|
||||
|
@ -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
@ -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
|
||||
});
|
||||
};
|
||||
})();
|
@ -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);
|
||||
}
|
||||
};
|
||||
})();
|
@ -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
@ -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())
|
||||
});
|
||||
}
|
||||
};
|
||||
})();
|
@ -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);
|
||||
}
|
||||
}
|
||||
|