Merge remote-tracking branch 'upstream/master'

Conflicts:
	Gruntfile.js
This commit is contained in:
Filipe Vieira 2014-05-06 02:53:18 +01:00
commit 8a85e953f1
10 changed files with 158 additions and 83 deletions

7
.gitignore vendored
View File

@ -12,15 +12,12 @@ npm-debug.log
# git stackdumps # git stackdumps
*.stackdump *.stackdump
# builds
build/*.js
build/*.css
# diffs # diffs
diff.txt diff.txt
# Closure compiler generated JS binary. # build destination
build/closure/closure_compiled_binary.js dest
# marked as private # marked as private
*.private.* *.private.*

View File

@ -36,6 +36,10 @@ module.exports = function(grunt) {
}; };
grunt.initConfig({ grunt.initConfig({
clean: {
before: ['dest'],
after: ['build/closure/closure_compiled_binary.js']
},
jshint: { jshint: {
options: { options: {
indent:2, indent:2,
@ -60,12 +64,39 @@ module.exports = function(grunt) {
base : '.', base : '.',
port : 4321 port : 4321
} }
}
},
express: {
regular: {
options: {
port: 9001,
hostname : 'localhost',
bases: ['dest']
}
}, },
serve : { debug: {
options : { options: {
base : '.', port: 9901,
port : 1234, hostname : 'localhost',
keepalive : true bases: ['src']
}
}
},
open : {
regular : {
path : 'http://localhost:9001/'
},
debug : {
path : 'http://localhost:9901/?debug'
}
},
watch: {
scripts: {
files: ['src/**/*.*'],
tasks: ['merge'],
options: {
spawn: false
} }
} }
}, },
@ -79,11 +110,11 @@ module.exports = function(grunt) {
separator : ';' separator : ';'
}, },
src : piskelScripts, src : piskelScripts,
dest : 'build/piskel-packaged.js' dest : 'dest/js/piskel-packaged.js'
}, },
css : { css : {
src : piskelStyles, src : piskelStyles,
dest : 'build/piskel-style-packaged.css' dest : 'dest/css/piskel-style-packaged.css'
} }
}, },
uglify : { uglify : {
@ -92,10 +123,20 @@ module.exports = function(grunt) {
}, },
my_target : { my_target : {
files : { files : {
'build/piskel-packaged-min.js' : ['build/piskel-packaged.js'] 'dest/js/piskel-packaged-min.js' : ['dest/js/piskel-packaged.js']
} }
} }
}, },
copy: {
main: {
files: [
{src: ['src/piskel-boot.js'], dest: 'dest/piskel-boot.js'},
{src: ['src/js/lib/iframeLoader.js'], dest: 'dest/js/lib/iframeLoader.js'},
{expand: true, src: ['img/**'], cwd: 'src/', dest: 'dest/', filter: 'isFile'},
{expand: true, src: ['**/*.html'], cwd: 'src/', dest: 'dest/', filter: 'isFile'}
]
}
},
closureCompiler: { closureCompiler: {
options: { options: {
// [REQUIRED] Path to closure compiler // [REQUIRED] Path to closure compiler
@ -146,26 +187,18 @@ module.exports = function(grunt) {
// This generated JS binary is currently not used and even excluded from source control using .gitignore. // This generated JS binary is currently not used and even excluded from source control using .gitignore.
dest: 'build/closure/closure_compiled_binary.js' dest: 'build/closure/closure_compiled_binary.js'
}, }
}, },
nodewebkit: { nodewebkit: {
options: { options: {
build_dir: './build', // Where the build version of my node-webkit app is saved build_dir: './dest', // Where the build version of my node-webkit app is saved
mac: true, mac: true,
win: true, win: true,
linux32: true, linux32: true,
linux64: true linux64: true
}, },
src: ['./**/*'] src: ['./**/*']
}, }
copy: {
desktop: {
files: [
{expand: true, cwd: "build/", src: ['*'], dest: 'desktop/build/', filter: 'isFile'},
{expand: true, cwd: "src/", src: ['**'], dest: 'desktop/'},
]
}
}
}); });
grunt.config.set('leadingIndent.indentation', 'spaces'); grunt.config.set('leadingIndent.indentation', 'spaces');
@ -179,12 +212,17 @@ module.exports = function(grunt) {
src: ['src/css/**/*.css'] src: ['src/css/**/*.css']
}); });
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-closure-tools'); grunt.loadNpmTasks('grunt-closure-tools');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-express');
grunt.loadNpmTasks('grunt-ghost'); grunt.loadNpmTasks('grunt-ghost');
grunt.loadNpmTasks('grunt-open');
grunt.loadNpmTasks('grunt-leading-indent'); grunt.loadNpmTasks('grunt-leading-indent');
grunt.loadNpmTasks('grunt-node-webkit-builder'); grunt.loadNpmTasks('grunt-node-webkit-builder');
grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-copy');
@ -193,23 +231,27 @@ module.exports = function(grunt) {
grunt.registerTask('lint', ['leadingIndent:jsFiles', 'leadingIndent:cssFiles', 'jshint']); grunt.registerTask('lint', ['leadingIndent:jsFiles', 'leadingIndent:cssFiles', 'jshint']);
// Validate & Test // Validate & Test
grunt.registerTask('test', ['leadingIndent:jsFiles', 'leadingIndent:cssFiles', 'jshint', 'compile', 'connect:test', 'ghost:default']); grunt.registerTask('test', ['lint', 'compile', 'connect:test', 'ghost:default']);
// Validate & Test (faster version) will NOT work on travis !! // Validate & Test (faster version) will NOT work on travis !!
grunt.registerTask('precommit', ['leadingIndent:jsFiles', 'leadingIndent:cssFiles', 'jshint', 'compile', 'connect:test', 'ghost:local']); grunt.registerTask('precommit', ['lint', 'compile', 'connect:test', 'ghost:local']);
// Compile JS code (eg verify JSDoc annotation and types, no actual minified code generated). // Compile JS code (eg verify JSDoc annotation and types, no actual minified code generated).
grunt.registerTask('compile', ['closureCompiler:compile']); grunt.registerTask('compile', ['closureCompiler:compile', 'clean:after']);
grunt.registerTask('merge', ['concat:js', 'concat:css', 'uglify']); grunt.registerTask('merge', ['concat:js', 'concat:css', 'uglify', 'copy']);
// Validate & Build // Validate & Build
grunt.registerTask('default', ['leadingIndent:jsFiles', 'leadingIndent:cssFiles', 'jshint', 'concat:js', 'concat:css', 'compile', 'uglify']); grunt.registerTask('default', ['clean:before', 'lint', 'compile', 'merge']);
// Start webserver
grunt.registerTask('serve', ['connect:serve']);
// Build stand alone app with nodewebkit // Build stand alone app with nodewebkit
grunt.registerTask('desktop', ['compile', 'merge', 'copy:desktop', 'nodewebkit']); grunt.registerTask('desktop', ['default', 'nodewebkit']);
grunt.registerTask('server', ['merge', 'express:regular', 'open:regular', 'express-keepalive']);
// Start webserver and watch for changes
grunt.registerTask('server:watch', ['server', 'watch']);
// Start webserver on src folder, in debug mode
grunt.registerTask('server:debug', ['express:debug', 'open:debug', 'express-keepalive']);
}; };

View File

@ -1,7 +1,7 @@
{ {
"author": "Julian Descottes, Vincent Renaudin", "author": "Julian Descottes, Vincent Renaudin",
"name": "piskel", "name": "piskel",
"main": "./desktop/index.html", "main": "./dest/index.html",
"description": "Web based 2d animations editor", "description": "Web based 2d animations editor",
"version": "0.0.1", "version": "0.0.1",
"homepage": "http://github.com/juliandescottes/piskel", "homepage": "http://github.com/juliandescottes/piskel",
@ -15,15 +15,19 @@
}, },
"devDependencies": { "devDependencies": {
"grunt": "~0.4.1", "grunt": "~0.4.1",
"grunt-contrib-clean": "0.5.0",
"grunt-contrib-connect": "0.3.0", "grunt-contrib-connect": "0.3.0",
"grunt-contrib-concat": "0.1.2", "grunt-contrib-concat": "0.1.2",
"grunt-contrib-copy": "0.5.0",
"grunt-contrib-jshint": "0.5.4", "grunt-contrib-jshint": "0.5.4",
"grunt-contrib-uglify": "0.2.2", "grunt-contrib-uglify": "0.2.2",
"grunt-contrib-watch": "0.6.1",
"grunt-express": "1.0",
"grunt-ghost": "1.0.12", "grunt-ghost": "1.0.12",
"grunt-open": "0.2.3",
"grunt-leading-indent": "0.1.0", "grunt-leading-indent": "0.1.0",
"grunt-closure-tools": "~0.8.3", "grunt-closure-tools": "~0.8.3",
"grunt-node-webkit-builder": "~0.1.21", "grunt-node-webkit-builder": "~0.1.21"
"grunt-contrib-copy": "~0.5.0"
}, },
"window": { "window": {
"toolbar": false "toolbar": false

View File

@ -60,7 +60,6 @@
$.subscribe(Events.USER_SETTINGS_CHANGED, $.proxy(this.onUserSettingsChange_, this)); $.subscribe(Events.USER_SETTINGS_CHANGED, $.proxy(this.onUserSettingsChange_, this));
$.subscribe(Events.FRAME_SIZE_CHANGED, $.proxy(this.onFrameSizeChanged_, this)); $.subscribe(Events.FRAME_SIZE_CHANGED, $.proxy(this.onFrameSizeChanged_, this));
// this.afterWindowResize_.bind(this);
window.setTimeout(this.afterWindowResize_.bind(this), 100); window.setTimeout(this.afterWindowResize_.bind(this), 100);
}; };

View File

@ -17,6 +17,8 @@
this.resizeForm = $("[name=resize-form]"); this.resizeForm = $("[name=resize-form]");
this.resizeForm.submit(this.onResizeFormSubmit_.bind(this)); this.resizeForm.submit(this.onResizeFormSubmit_.bind(this));
this.resizeContentCheckbox = $(".resize-content-checkbox");
}; };
ns.ResizeController.prototype.onResizeFormSubmit_ = function (evt) { ns.ResizeController.prototype.onResizeFormSubmit_ = function (evt) {
@ -25,31 +27,41 @@
var width = parseInt(this.resizeWidth.val(), 10); var width = parseInt(this.resizeWidth.val(), 10);
var height = parseInt(this.resizeHeight.val(), 10); var height = parseInt(this.resizeHeight.val(), 10);
var layers = [];
var fromLayers = this.piskelController.getLayers();
for (var i = 0 ; i < fromLayers.length ; i++) {
var frames = [];
var fromFrames = fromLayers[i].getFrames();
for (var j = 0 ; j < fromFrames.length ; j++) {
var frame = new pskl.model.Frame(width, height);
this.copyFromFrameToFrame(fromFrames[j], frame);
frames.push(frame);
}
var layer = pskl.model.Layer.fromFrames(fromLayers[i].getName(), frames);
layers.push(layer);
}
var piskel = pskl.model.Piskel.fromLayers(layers, this.piskelController.getPiskel().getDescriptor()); var resizeContentEnabled = this.isResizeContentEnabled_();
var resizedLayers = this.piskelController.getLayers().map(this.resizeLayer_.bind(this));
var piskel = pskl.model.Piskel.fromLayers(resizedLayers, this.piskelController.getPiskel().getDescriptor());
pskl.app.piskelController.setPiskel(piskel); pskl.app.piskelController.setPiskel(piskel);
$.publish(Events.CLOSE_SETTINGS_DRAWER); $.publish(Events.CLOSE_SETTINGS_DRAWER);
}; };
ns.ResizeController.prototype.copyFromFrameToFrame = function (from, to) { ns.ResizeController.prototype.resizeLayer_ = function (layer) {
from.forEachPixel(function (color, x, y) { var resizedFrames = layer.getFrames().map(this.resizeFrame_.bind(this));
if (x < to.getWidth() && y < to.getHeight()) { return pskl.model.Layer.fromFrames(layer.getName(), resizedFrames);
to.setPixel(x, y, color); };
}
}); ns.ResizeController.prototype.resizeFrame_ = function (frame) {
var width = parseInt(this.resizeWidth.val(), 10);
var height = parseInt(this.resizeHeight.val(), 10);
var resizedFrame;
if (this.isResizeContentEnabled_()) {
resizedFrame = pskl.utils.FrameUtils.resize(frame, width, height, false);
} else {
resizedFrame = new pskl.model.Frame(width, height);
frame.forEachPixel(function (color, x, y) {
if (x < resizedFrame.getWidth() && y < resizedFrame.getHeight()) {
resizedFrame.setPixel(x, y, color);
}
});
}
return resizedFrame;
};
ns.ResizeController.prototype.isResizeContentEnabled_ = function () {
return !!this.resizeContentCheckbox.prop('checked');
}; };
ns.ResizeController.prototype.onCancelButtonClicked_ = function (evt) { ns.ResizeController.prototype.onCancelButtonClicked_ = function (evt) {

View File

@ -95,6 +95,8 @@
this.isExpanded = false; this.isExpanded = false;
this.currentSetting = null; this.currentSetting = null;
document.activeElement.blur();
}; };
})(); })();

View File

@ -78,8 +78,9 @@
throw 'Could not find previous SNAPSHOT saved in history stateQueue'; throw 'Could not find previous SNAPSHOT saved in history stateQueue';
} }
var piskelSnapshot = this.getSnapshotFromState_(snapshotIndex); var serializedPiskel = this.getSnapshotFromState_(snapshotIndex);
this.loadPiskel(piskelSnapshot, this.onPiskelLoadedCallback.bind(this, index, snapshotIndex)); var onPiskelLoadedCb = this.onPiskelLoaded_.bind(this, index, snapshotIndex);
pskl.utils.serialization.Deserializer.deserialize(serializedPiskel, onPiskelLoadedCb);
} }
}; };
@ -98,16 +99,11 @@
return piskelSnapshot; return piskelSnapshot;
}; };
ns.HistoryService.prototype.loadPiskel = function (piskel, callback) { ns.HistoryService.prototype.onPiskelLoaded_ = function (index, snapshotIndex, piskel) {
var descriptor = this.piskelController.piskel.getDescriptor(); var originalSize = this.getPiskelSize_();
pskl.utils.serialization.Deserializer.deserialize(piskel, function (deserializedPiskel) { piskel.setDescriptor(this.piskelController.piskel.getDescriptor());
deserializedPiskel.setDescriptor(descriptor); this.piskelController.setPiskel(piskel);
this.piskelController.setPiskel(deserializedPiskel);
callback(deserializedPiskel);
}.bind(this));
};
ns.HistoryService.prototype.onPiskelLoadedCallback = function (index, snapshotIndex, piskel) {
for (var i = snapshotIndex + 1 ; i <= index ; i++) { for (var i = snapshotIndex + 1 ; i <= index ; i++) {
var state = this.stateQueue[i]; var state = this.stateQueue[i];
this.setupState(state); this.setupState(state);
@ -118,6 +114,13 @@
this.setupState(lastState); this.setupState(lastState);
this.currentIndex = index; this.currentIndex = index;
$.publish(Events.PISKEL_RESET); $.publish(Events.PISKEL_RESET);
if (originalSize !== this.getPiskelSize_()) {
$.publish(Events.FRAME_SIZE_CHANGED);
}
};
ns.HistoryService.prototype.getPiskelSize_ = function () {
return this.piskelController.getWidth() + 'x' + this.piskelController.getHeight();
}; };
ns.HistoryService.prototype.setupState = function (state) { ns.HistoryService.prototype.setupState = function (state) {

View File

@ -22,6 +22,12 @@
}); });
}, },
resize : function (frame, targetWidth, targetHeight, smoothing) {
var image = pskl.utils.FrameUtils.toImage(frame);
var resizedImage = pskl.utils.ImageResizer.resize(image, targetWidth, targetHeight, smoothing);
return pskl.utils.FrameUtils.createFromImage(resizedImage);
},
/** /**
* Alpha compositing using porter duff algorithm : * Alpha compositing using porter duff algorithm :
* http://en.wikipedia.org/wiki/Alpha_compositing * http://en.wikipedia.org/wiki/Alpha_compositing
@ -151,6 +157,12 @@
componentToHex : function (c) { componentToHex : function (c) {
var hex = c.toString(16); var hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex; return hex.length == 1 ? "0" + hex : hex;
},
toImage : function (frame) {
var canvasRenderer = new pskl.rendering.CanvasRenderer(frame, 1);
canvasRenderer.drawTransparentAs(Constants.TRANSPARENT_COLOR);
return canvasRenderer.render();
} }
}; };
})(); })();

View File

@ -59,11 +59,11 @@
} else { } else {
var script; var script;
if (window.location.href.indexOf("pack") != -1) { if (window.location.href.indexOf("pack") != -1) {
script = "build/piskel-packaged.js"; script = "js/piskel-packaged.js";
} else { } else {
script = "build/piskel-packaged-min.js"; script = "js/piskel-packaged-min.js";
} }
loadStyle('build/piskel-style-packaged.css'); loadStyle('css/piskel-style-packaged.css');
var loaderInterval = window.setInterval(function () { var loaderInterval = window.setInterval(function () {
if (document.querySelectorAll("[data-iframe-loader]").length === 0) { if (document.querySelectorAll("[data-iframe-loader]").length === 0) {

View File

@ -10,6 +10,10 @@
<input type="text" class="textfield resize-size-field" name="resize-width"/>x <input type="text" class="textfield resize-size-field" name="resize-width"/>x
<input type="text" class="textfield resize-size-field" name="resize-height"/> <input type="text" class="textfield resize-size-field" name="resize-height"/>
</div> </div>
<div class="resize-section">
<span class="resize-section-title resize-section-title-small">Resize canvas content : </span>
<input type="checkbox" class="resize-content-checkbox" name="resize-content-checkbox" value="true"/>
</div>
<input type="submit" class="button button-primary resize-button" value="Resize" /> <input type="submit" class="button button-primary resize-button" value="Resize" />
<input type="button" class="button resize-cancel-button" value="Cancel" /> <input type="button" class="button resize-cancel-button" value="Cancel" />
</form> </form>