mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Merge from master + bugfixing on b64
This commit is contained in:
commit
c23de31e07
38
Gruntfile.js
38
Gruntfile.js
@ -10,16 +10,24 @@
|
||||
* If you run this task locally, it may require some env set up first.
|
||||
*/
|
||||
|
||||
module.exports = function (grunt) {
|
||||
module.exports = function(grunt) {
|
||||
grunt.initConfig({
|
||||
jshint : {
|
||||
jshint: {
|
||||
/*options: {
|
||||
"evil": true,
|
||||
"asi": true,
|
||||
"smarttabs": true,
|
||||
"eqnull": true
|
||||
},*/
|
||||
files : [
|
||||
"evil": true,
|
||||
"asi": true,
|
||||
"smarttabs": true,
|
||||
"eqnull": true
|
||||
},*/
|
||||
options: {
|
||||
indent:2,
|
||||
undef : true,
|
||||
latedef : true,
|
||||
browser : true,
|
||||
jquery : true,
|
||||
globals : {'pskl':true, 'Events':true, 'Constants':true, 'console' : true, 'module':true, 'require':true}
|
||||
},
|
||||
files: [
|
||||
'Gruntfile.js',
|
||||
'package.json',
|
||||
'js/**/*.js',
|
||||
@ -69,13 +77,23 @@ module.exports = function (grunt) {
|
||||
}
|
||||
});
|
||||
|
||||
grunt.config.set('leadingIndent.indentation', 'spaces');
|
||||
grunt.config.set('leadingIndent.jsFiles', {
|
||||
src: ['js/**/*.js','!js/lib/**/*.js']
|
||||
});
|
||||
grunt.config.set('leadingIndent.cssFiles', {
|
||||
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-ghost');
|
||||
grunt.loadNpmTasks('grunt-leading-indent');
|
||||
|
||||
grunt.registerTask('lint', ['leadingIndent:jsFiles', 'leadingIndent:cssFiles', 'jshint']);
|
||||
grunt.registerTask('test', ['leadingIndent:jsFiles', 'leadingIndent:cssFiles', 'jshint', 'connect', 'ghost']);
|
||||
|
||||
grunt.registerTask('default', ['jshint', 'concat', 'uglify']);
|
||||
grunt.registerTask('lint', ['jshint']);
|
||||
grunt.registerTask('test', ['jshint', 'connect', 'ghost']);
|
||||
};
|
||||
|
@ -1,36 +1,38 @@
|
||||
// TODO(grosbouddha): put under pskl namespace.
|
||||
var Constants = {
|
||||
DEFAULT_SIZE : {
|
||||
height : 32,
|
||||
width : 32
|
||||
},
|
||||
DEFAULT_SIZE : {
|
||||
height : 32,
|
||||
width : 32
|
||||
},
|
||||
|
||||
MAX_HEIGHT : 128,
|
||||
MAX_WIDTH : 128,
|
||||
MAX_HEIGHT : 128,
|
||||
MAX_WIDTH : 128,
|
||||
|
||||
DEFAULT_PEN_COLOR : '#000000',
|
||||
TRANSPARENT_COLOR : 'TRANSPARENT',
|
||||
|
||||
/*
|
||||
* Fake semi-transparent color used to highlight transparent
|
||||
* strokes and rectangles:
|
||||
*/
|
||||
SELECTION_TRANSPARENT_COLOR: 'rgba(255, 255, 255, 0.6)',
|
||||
PREVIEW_FILM_SIZE : 120,
|
||||
|
||||
/*
|
||||
* When a tool is hovering the drawing canvas, we highlight the eventual
|
||||
* pixel target with this color:
|
||||
*/
|
||||
TOOL_TARGET_HIGHLIGHT_COLOR: 'rgba(255, 255, 255, 0.2)',
|
||||
|
||||
/*
|
||||
* Default entry point for piskel web service:
|
||||
*/
|
||||
PISKEL_SERVICE_URL: 'http://3.piskel-app.appspot.com',
|
||||
DEFAULT_PEN_COLOR : '#000000',
|
||||
TRANSPARENT_COLOR : 'TRANSPARENT',
|
||||
|
||||
/*
|
||||
* Fake semi-transparent color used to highlight transparent
|
||||
* strokes and rectangles:
|
||||
*/
|
||||
SELECTION_TRANSPARENT_COLOR: 'rgba(255, 255, 255, 0.6)',
|
||||
|
||||
GRID_STROKE_WIDTH: 1,
|
||||
GRID_STROKE_COLOR: "lightgray",
|
||||
/*
|
||||
* When a tool is hovering the drawing canvas, we highlight the eventual
|
||||
* pixel target with this color:
|
||||
*/
|
||||
TOOL_TARGET_HIGHLIGHT_COLOR: 'rgba(255, 255, 255, 0.2)',
|
||||
|
||||
/*
|
||||
* Default entry point for piskel web service:
|
||||
*/
|
||||
PISKEL_SERVICE_URL: 'http://3.piskel-app.appspot.com',
|
||||
|
||||
LEFT_BUTTON : "left_button_1",
|
||||
RIGHT_BUTTON : "right_button_2"
|
||||
GRID_STROKE_WIDTH: 1,
|
||||
GRID_STROKE_COLOR: "lightgray",
|
||||
|
||||
LEFT_BUTTON : "left_button_1",
|
||||
RIGHT_BUTTON : "right_button_2"
|
||||
};
|
104
js/Events.js
104
js/Events.js
@ -1,64 +1,64 @@
|
||||
// TODO(grosbouddha): put under pskl namespace.
|
||||
Events = {
|
||||
|
||||
TOOL_SELECTED : "TOOL_SELECTED",
|
||||
TOOL_RELEASED : "TOOL_RELEASED",
|
||||
PRIMARY_COLOR_SELECTED: "PRIMARY_COLOR_SELECTED",
|
||||
PRIMARY_COLOR_UPDATED: "PRIMARY_COLOR_UPDATED",
|
||||
SECONDARY_COLOR_SELECTED: "SECONDARY_COLOR_SELECTED",
|
||||
SECONDARY_COLOR_UPDATED: "SECONDARY_COLOR_UPDATED",
|
||||
|
||||
TOOL_SELECTED : "TOOL_SELECTED",
|
||||
TOOL_RELEASED : "TOOL_RELEASED",
|
||||
PRIMARY_COLOR_SELECTED: "PRIMARY_COLOR_SELECTED",
|
||||
PRIMARY_COLOR_UPDATED: "PRIMARY_COLOR_UPDATED",
|
||||
SECONDARY_COLOR_SELECTED: "SECONDARY_COLOR_SELECTED",
|
||||
SECONDARY_COLOR_UPDATED: "SECONDARY_COLOR_UPDATED",
|
||||
|
||||
/**
|
||||
* When this event is emitted, a request is sent to the localstorage
|
||||
* Service to save the current framesheet. The storage service
|
||||
* may not immediately store data (internal throttling of requests).
|
||||
*/
|
||||
LOCALSTORAGE_REQUEST: "LOCALSTORAGE_REQUEST",
|
||||
/**
|
||||
* When this event is emitted, a request is sent to the localstorage
|
||||
* Service to save the current framesheet. The storage service
|
||||
* may not immediately store data (internal throttling of requests).
|
||||
*/
|
||||
LOCALSTORAGE_REQUEST: "LOCALSTORAGE_REQUEST",
|
||||
|
||||
CANVAS_RIGHT_CLICKED: "CANVAS_RIGHT_CLICKED",
|
||||
CANVAS_RIGHT_CLICKED: "CANVAS_RIGHT_CLICKED",
|
||||
|
||||
/**
|
||||
* Event to request a refresh of the display.
|
||||
* A bit overkill but, it's just workaround in our current drawing system.
|
||||
* TODO: Remove or rework when redraw system is refactored.
|
||||
*/
|
||||
REFRESH: "REFRESH",
|
||||
/**
|
||||
* Event to request a refresh of the display.
|
||||
* A bit overkill but, it's just workaround in our current drawing system.
|
||||
* TODO: Remove or rework when redraw system is refactored.
|
||||
*/
|
||||
REFRESH: "REFRESH",
|
||||
|
||||
/**
|
||||
* Temporary event to bind the redraw of right preview film to the canvas.
|
||||
* This redraw should be driven by model updates.
|
||||
* TODO(vincz): Remove.
|
||||
*/
|
||||
REDRAW_PREVIEWFILM: "REDRAW_PREVIEWFILM",
|
||||
/**
|
||||
* Temporary event to bind the redraw of right preview film to the canvas.
|
||||
* This redraw should be driven by model updates.
|
||||
* TODO(vincz): Remove.
|
||||
*/
|
||||
REDRAW_PREVIEWFILM: "REDRAW_PREVIEWFILM",
|
||||
|
||||
/**
|
||||
* Fired each time a user setting change.
|
||||
* The payload will be:
|
||||
* 1st argument: Name of the settings
|
||||
* 2nd argument: New value
|
||||
*/
|
||||
USER_SETTINGS_CHANGED: "USER_SETTINGS_CHANGED",
|
||||
|
||||
/**
|
||||
* The framesheet was reseted and is now probably drastically different.
|
||||
* Number of frames, content of frames, color used for the palette may have changed.
|
||||
*/
|
||||
FRAMESHEET_RESET: "FRAMESHEET_RESET",
|
||||
/**
|
||||
* Fired each time a user setting change.
|
||||
* The payload will be:
|
||||
* 1st argument: Name of the settings
|
||||
* 2nd argument: New value
|
||||
*/
|
||||
USER_SETTINGS_CHANGED: "USER_SETTINGS_CHANGED",
|
||||
|
||||
/**
|
||||
* The framesheet was reseted and is now probably drastically different.
|
||||
* Number of frames, content of frames, color used for the palette may have changed.
|
||||
*/
|
||||
FRAMESHEET_RESET: "FRAMESHEET_RESET",
|
||||
|
||||
FRAME_SIZE_CHANGED : "FRAME_SIZE_CHANGED",
|
||||
FRAME_SIZE_CHANGED : "FRAME_SIZE_CHANGED",
|
||||
|
||||
CURRENT_FRAME_SET: "CURRENT_FRAME_SET",
|
||||
CURRENT_FRAME_SET: "CURRENT_FRAME_SET",
|
||||
|
||||
SELECTION_CREATED: "SELECTION_CREATED",
|
||||
SELECTION_MOVE_REQUEST: "SELECTION_MOVE_REQUEST",
|
||||
SELECTION_DISMISSED: "SELECTION_DISMISSED",
|
||||
|
||||
SHOW_NOTIFICATION: "SHOW_NOTIFICATION",
|
||||
HIDE_NOTIFICATION: "HIDE_NOTIFICATION",
|
||||
SELECTION_CREATED: "SELECTION_CREATED",
|
||||
SELECTION_MOVE_REQUEST: "SELECTION_MOVE_REQUEST",
|
||||
SELECTION_DISMISSED: "SELECTION_DISMISSED",
|
||||
|
||||
SHOW_NOTIFICATION: "SHOW_NOTIFICATION",
|
||||
HIDE_NOTIFICATION: "HIDE_NOTIFICATION",
|
||||
|
||||
UNDO: "UNDO",
|
||||
REDO: "REDO",
|
||||
CUT: "CUT",
|
||||
COPY: "COPY",
|
||||
PASTE: "PASTE"
|
||||
UNDO: "UNDO",
|
||||
REDO: "REDO",
|
||||
CUT: "CUT",
|
||||
COPY: "COPY",
|
||||
PASTE: "PASTE"
|
||||
};
|
@ -1,67 +1,67 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller");
|
||||
ns.AnimatedPreviewController = function (framesheet, container, dpi) {
|
||||
this.framesheet = framesheet;
|
||||
this.container = container;
|
||||
var ns = $.namespace("pskl.controller");
|
||||
ns.AnimatedPreviewController = function (framesheet, container, dpi) {
|
||||
this.framesheet = framesheet;
|
||||
this.container = container;
|
||||
|
||||
this.elapsedTime = 0;
|
||||
this.elapsedTime = 0;
|
||||
this.currentIndex = 0;
|
||||
|
||||
this.fps = parseInt($("#preview-fps")[0].value, 10);
|
||||
|
||||
var renderingOptions = {
|
||||
"dpi": this.calculateDPI_()
|
||||
};
|
||||
this.renderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions);
|
||||
|
||||
$.subscribe(Events.FRAME_SIZE_CHANGED, this.updateDPI_.bind(this));
|
||||
};
|
||||
|
||||
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));
|
||||
};
|
||||
|
||||
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");
|
||||
};
|
||||
|
||||
ns.AnimatedPreviewController.prototype.render = function (delta) {
|
||||
this.elapsedTime += delta;
|
||||
var index = Math.floor(this.elapsedTime / (1000/this.fps));
|
||||
if (index != this.currentIndex) {
|
||||
this.currentIndex = index;
|
||||
if (!this.framesheet.hasFrameAtIndex(this.currentIndex)) {
|
||||
this.currentIndex = 0;
|
||||
this.elapsedTime = 0;
|
||||
}
|
||||
this.renderer.render(this.framesheet.getFrameByIndex(this.currentIndex));
|
||||
}
|
||||
};
|
||||
|
||||
this.fps = parseInt($("#preview-fps")[0].value, 10);
|
||||
|
||||
var renderingOptions = {
|
||||
"dpi": this.calculateDPI_()
|
||||
};
|
||||
this.renderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions);
|
||||
/**
|
||||
* Calculate the preview DPI depending on the framesheet size
|
||||
*/
|
||||
ns.AnimatedPreviewController.prototype.calculateDPI_ = function () {
|
||||
var previewSize = 200,
|
||||
framePixelHeight = this.framesheet.getCurrentFrame().getHeight(),
|
||||
framePixelWidth = this.framesheet.getCurrentFrame().getWidth();
|
||||
// TODO (julz) : should have a utility to get a Size from framesheet easily (what about empty framesheets though ?)
|
||||
|
||||
//return pskl.PixelUtils.calculateDPIForContainer($(".preview-container"), framePixelHeight, framePixelWidth);
|
||||
return pskl.PixelUtils.calculateDPI(previewSize, previewSize, framePixelHeight, framePixelWidth);
|
||||
};
|
||||
|
||||
$.subscribe(Events.FRAME_SIZE_CHANGED, this.updateDPI_.bind(this));
|
||||
};
|
||||
|
||||
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));
|
||||
};
|
||||
|
||||
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");
|
||||
};
|
||||
|
||||
ns.AnimatedPreviewController.prototype.render = function (delta) {
|
||||
this.elapsedTime += delta;
|
||||
var index = Math.floor(this.elapsedTime / (1000/this.fps));
|
||||
if (index != this.currentIndex) {
|
||||
this.currentIndex = index;
|
||||
if (!this.framesheet.hasFrameAtIndex(this.currentIndex)) {
|
||||
this.currentIndex = 0;
|
||||
this.elapsedTime = 0;
|
||||
}
|
||||
this.renderer.render(this.framesheet.getFrameByIndex(this.currentIndex));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the preview DPI depending on the framesheet size
|
||||
*/
|
||||
ns.AnimatedPreviewController.prototype.calculateDPI_ = function () {
|
||||
var previewSize = 200,
|
||||
framePixelHeight = this.framesheet.getCurrentFrame().getHeight(),
|
||||
framePixelWidth = this.framesheet.getCurrentFrame().getWidth();
|
||||
// TODO (julz) : should have a utility to get a Size from framesheet easily (what about empty framesheets though ?)
|
||||
|
||||
//return pskl.PixelUtils.calculateDPIForContainer($(".preview-container"), framePixelHeight, framePixelWidth);
|
||||
return pskl.PixelUtils.calculateDPI(previewSize, previewSize, framePixelHeight, framePixelWidth);
|
||||
};
|
||||
|
||||
ns.AnimatedPreviewController.prototype.updateDPI_ = function () {
|
||||
this.dpi = this.calculateDPI_();
|
||||
this.renderer.updateDPI(this.dpi);
|
||||
};
|
||||
ns.AnimatedPreviewController.prototype.updateDPI_ = function () {
|
||||
this.dpi = this.calculateDPI_();
|
||||
this.renderer.updateDPI(this.dpi);
|
||||
};
|
||||
})();
|
@ -25,8 +25,6 @@
|
||||
this.renderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions, "drawing-canvas");
|
||||
this.overlayRenderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions, "canvas-overlay");
|
||||
|
||||
this.renderer.init(framesheet.getCurrentFrame());
|
||||
this.overlayRenderer.init(this.overlayFrame);
|
||||
|
||||
// State of drawing controller:
|
||||
this.isClicked = false;
|
||||
@ -35,12 +33,18 @@
|
||||
this.currentToolBehavior = null;
|
||||
this.primaryColor = Constants.DEFAULT_PEN_COLOR;
|
||||
this.secondaryColor = Constants.TRANSPARENT_COLOR;
|
||||
};
|
||||
|
||||
ns.DrawingController.prototype.init = function () {
|
||||
this.renderer.render(this.framesheet.getCurrentFrame());
|
||||
this.overlayRenderer.render(this.overlayFrame);
|
||||
|
||||
this.initMouseBehavior();
|
||||
|
||||
$.subscribe(Events.TOOL_SELECTED, $.proxy(function(evt, toolBehavior) {
|
||||
console.log("Tool selected: ", toolBehavior);
|
||||
this.currentToolBehavior = toolBehavior;
|
||||
this.overlayFrame.clear();
|
||||
}, this));
|
||||
|
||||
/**
|
||||
@ -68,21 +72,21 @@
|
||||
|
||||
ns.DrawingController.prototype.initMouseBehavior = function() {
|
||||
var body = $('body');
|
||||
this.container.mousedown($.proxy(this.onMousedown_, this));
|
||||
this.container.mousemove($.proxy(this.onMousemove_, this));
|
||||
body.mouseup($.proxy(this.onMouseup_, this));
|
||||
|
||||
// Deactivate right click:
|
||||
body.contextmenu(this.onCanvasContextMenu_);
|
||||
this.container.mousedown($.proxy(this.onMousedown_, this));
|
||||
this.container.mousemove($.proxy(this.onMousemove_, this));
|
||||
body.mouseup($.proxy(this.onMouseup_, this));
|
||||
|
||||
// Deactivate right click:
|
||||
body.contextmenu(this.onCanvasContextMenu_);
|
||||
};
|
||||
|
||||
|
||||
|
||||
ns.DrawingController.prototype.startDPIUpdateTimer_ = function () {
|
||||
if (this.dpiUpdateTimer) {
|
||||
window.clearInterval(this.dpiUpdateTimer);
|
||||
}
|
||||
this.dpiUpdateTimer = window.setTimeout($.proxy(this.updateDPI_, this), 200);
|
||||
if (this.dpiUpdateTimer) {
|
||||
window.clearInterval(this.dpiUpdateTimer);
|
||||
}
|
||||
this.dpiUpdateTimer = window.setTimeout($.proxy(this.updateDPI_, this), 200);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -98,144 +102,144 @@
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.onMousedown_ = function (event) {
|
||||
this.isClicked = true;
|
||||
|
||||
if(event.button == 2) { // right click
|
||||
this.isRightClicked = true;
|
||||
$.publish(Events.CANVAS_RIGHT_CLICKED);
|
||||
}
|
||||
this.isClicked = true;
|
||||
|
||||
if(event.button == 2) { // right click
|
||||
this.isRightClicked = true;
|
||||
$.publish(Events.CANVAS_RIGHT_CLICKED);
|
||||
}
|
||||
|
||||
var coords = this.getSpriteCoordinates(event);
|
||||
var coords = this.getSpriteCoordinates(event);
|
||||
|
||||
this.currentToolBehavior.applyToolAt(
|
||||
coords.col, coords.row,
|
||||
this.getCurrentColor_(),
|
||||
this.framesheet.getCurrentFrame(),
|
||||
this.overlayFrame,
|
||||
this.wrapEvtInfo_(event)
|
||||
);
|
||||
|
||||
this.currentToolBehavior.applyToolAt(
|
||||
coords.col, coords.row,
|
||||
this.getCurrentColor_(),
|
||||
this.framesheet.getCurrentFrame(),
|
||||
this.overlayFrame,
|
||||
this.wrapEvtInfo_(event)
|
||||
);
|
||||
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST);
|
||||
};
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST);
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.onMousemove_ = function (event) {
|
||||
var currentTime = new Date().getTime();
|
||||
// Throttling of the mousemove event:
|
||||
if ((currentTime - this.previousMousemoveTime) > 40 ) {
|
||||
var coords = this.getSpriteCoordinates(event);
|
||||
if (this.isClicked) {
|
||||
|
||||
this.currentToolBehavior.moveToolAt(
|
||||
coords.col, coords.row,
|
||||
this.getCurrentColor_(),
|
||||
this.framesheet.getCurrentFrame(),
|
||||
this.overlayFrame,
|
||||
this.wrapEvtInfo_(event)
|
||||
);
|
||||
|
||||
// TODO(vincz): Find a way to move that to the model instead of being at the interaction level.
|
||||
// Eg when drawing, it may make sense to have it here. However for a non drawing tool,
|
||||
// you don't need to draw anything when mousemoving and you request useless localStorage.
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST);
|
||||
} else {
|
||||
|
||||
this.currentToolBehavior.moveUnactiveToolAt(
|
||||
coords.col, coords.row,
|
||||
this.getCurrentColor_(),
|
||||
this.framesheet.getCurrentFrame(),
|
||||
this.overlayFrame,
|
||||
this.wrapEvtInfo_(event)
|
||||
);
|
||||
}
|
||||
this.previousMousemoveTime = currentTime;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.onMouseup_ = function (event) {
|
||||
if(this.isClicked || this.isRightClicked) {
|
||||
// A mouse button was clicked on the drawing canvas before this mouseup event,
|
||||
// the user was probably drawing on the canvas.
|
||||
// Note: The mousemove movement (and the mouseup) may end up outside
|
||||
// of the drawing canvas.
|
||||
|
||||
this.isClicked = false;
|
||||
this.isRightClicked = false;
|
||||
|
||||
var coords = this.getSpriteCoordinates(event);
|
||||
//console.log("mousemove: col: " + spriteCoordinate.col + " - row: " + spriteCoordinate.row);
|
||||
this.currentToolBehavior.releaseToolAt(
|
||||
ns.DrawingController.prototype.onMousemove_ = function (event) {
|
||||
var currentTime = new Date().getTime();
|
||||
// Throttling of the mousemove event:
|
||||
if ((currentTime - this.previousMousemoveTime) > 40 ) {
|
||||
var coords = this.getSpriteCoordinates(event);
|
||||
if (this.isClicked) {
|
||||
|
||||
this.currentToolBehavior.moveToolAt(
|
||||
coords.col, coords.row,
|
||||
this.getCurrentColor_(),
|
||||
this.framesheet.getCurrentFrame(),
|
||||
this.overlayFrame,
|
||||
this.wrapEvtInfo_(event)
|
||||
);
|
||||
|
||||
$.publish(Events.TOOL_RELEASED);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.wrapEvtInfo_ = function (event) {
|
||||
var evtInfo = {};
|
||||
if (event.button === 0) {
|
||||
evtInfo.button = Constants.LEFT_BUTTON;
|
||||
} else if (event.button == 2) {
|
||||
evtInfo.button = Constants.RIGHT_BUTTON;
|
||||
}
|
||||
return evtInfo;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.getRelativeCoordinates = function (clientX, clientY) {
|
||||
var canvasPageOffset = this.container.offset();
|
||||
return {
|
||||
x : clientX - canvasPageOffset.left,
|
||||
y : clientY - canvasPageOffset.top
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.getSpriteCoordinates = function(event) {
|
||||
var coords = this.getRelativeCoordinates(event.clientX, event.clientY);
|
||||
return this.renderer.convertPixelCoordinatesIntoSpriteCoordinate(coords);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.getCurrentColor_ = function () {
|
||||
if(this.isRightClicked) {
|
||||
return this.secondaryColor;
|
||||
|
||||
// TODO(vincz): Find a way to move that to the model instead of being at the interaction level.
|
||||
// Eg when drawing, it may make sense to have it here. However for a non drawing tool,
|
||||
// you don't need to draw anything when mousemoving and you request useless localStorage.
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST);
|
||||
} else {
|
||||
return this.primaryColor;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.onCanvasContextMenu_ = function (event) {
|
||||
if ($(event.target).closest('#drawing-canvas-container').length) {
|
||||
// Deactivate right click on drawing canvas only.
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
event.cancelBubble = true;
|
||||
return false;
|
||||
}
|
||||
this.currentToolBehavior.moveUnactiveToolAt(
|
||||
coords.col, coords.row,
|
||||
this.getCurrentColor_(),
|
||||
this.framesheet.getCurrentFrame(),
|
||||
this.overlayFrame,
|
||||
this.wrapEvtInfo_(event)
|
||||
);
|
||||
}
|
||||
this.previousMousemoveTime = currentTime;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.onMouseup_ = function (event) {
|
||||
if(this.isClicked || this.isRightClicked) {
|
||||
// A mouse button was clicked on the drawing canvas before this mouseup event,
|
||||
// the user was probably drawing on the canvas.
|
||||
// Note: The mousemove movement (and the mouseup) may end up outside
|
||||
// of the drawing canvas.
|
||||
|
||||
this.isClicked = false;
|
||||
this.isRightClicked = false;
|
||||
|
||||
var coords = this.getSpriteCoordinates(event);
|
||||
//console.log("mousemove: col: " + spriteCoordinate.col + " - row: " + spriteCoordinate.row);
|
||||
this.currentToolBehavior.releaseToolAt(
|
||||
coords.col, coords.row,
|
||||
this.getCurrentColor_(),
|
||||
this.framesheet.getCurrentFrame(),
|
||||
this.overlayFrame,
|
||||
this.wrapEvtInfo_(event)
|
||||
);
|
||||
|
||||
$.publish(Events.TOOL_RELEASED);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.wrapEvtInfo_ = function (event) {
|
||||
var evtInfo = {};
|
||||
if (event.button === 0) {
|
||||
evtInfo.button = Constants.LEFT_BUTTON;
|
||||
} else if (event.button == 2) {
|
||||
evtInfo.button = Constants.RIGHT_BUTTON;
|
||||
}
|
||||
return evtInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.getRelativeCoordinates = function (clientX, clientY) {
|
||||
var canvasPageOffset = this.container.offset();
|
||||
return {
|
||||
x : clientX - canvasPageOffset.left,
|
||||
y : clientY - canvasPageOffset.top
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.getSpriteCoordinates = function(event) {
|
||||
var coords = this.getRelativeCoordinates(event.clientX, event.clientY);
|
||||
return this.renderer.convertPixelCoordinatesIntoSpriteCoordinate(coords);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.getCurrentColor_ = function () {
|
||||
if(this.isRightClicked) {
|
||||
return this.secondaryColor;
|
||||
} else {
|
||||
return this.primaryColor;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.onCanvasContextMenu_ = function (event) {
|
||||
if ($(event.target).closest('#drawing-canvas-container').length) {
|
||||
// Deactivate right click on drawing canvas only.
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
event.cancelBubble = true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
ns.DrawingController.prototype.render = function () {
|
||||
this.renderFrame();
|
||||
@ -271,11 +275,11 @@
|
||||
*/
|
||||
ns.DrawingController.prototype.calculateDPI_ = function() {
|
||||
var availableViewportHeight = $('#main-wrapper').height(),
|
||||
leftSectionWidth = $('.left-column').outerWidth(true),
|
||||
rightSectionWidth = $('.right-column').outerWidth(true),
|
||||
availableViewportWidth = $('#main-wrapper').width() - leftSectionWidth - rightSectionWidth,
|
||||
framePixelHeight = this.framesheet.getCurrentFrame().getHeight(),
|
||||
framePixelWidth = this.framesheet.getCurrentFrame().getWidth();
|
||||
leftSectionWidth = $('.left-column').outerWidth(true),
|
||||
rightSectionWidth = $('.right-column').outerWidth(true),
|
||||
availableViewportWidth = $('#main-wrapper').width() - leftSectionWidth - rightSectionWidth,
|
||||
framePixelHeight = this.framesheet.getCurrentFrame().getHeight(),
|
||||
framePixelWidth = this.framesheet.getCurrentFrame().getWidth();
|
||||
|
||||
if (pskl.UserSettings.get(pskl.UserSettings.SHOW_GRID)) {
|
||||
availableViewportWidth = availableViewportWidth - (framePixelWidth * Constants.GRID_STROKE_WIDTH);
|
||||
@ -299,7 +303,7 @@
|
||||
var currentFrameHeight = this.framesheet.getCurrentFrame().getHeight();
|
||||
var canvasHeight = currentFrameHeight * dpi;
|
||||
if (pskl.UserSettings.get(pskl.UserSettings.SHOW_GRID)) {
|
||||
canvasHeight += Constants.GRID_STROKE_WIDTH * currentFrameHeight;
|
||||
canvasHeight += Constants.GRID_STROKE_WIDTH * currentFrameHeight;
|
||||
}
|
||||
|
||||
var verticalGapInPixel = Math.floor(($('#main-wrapper').height() - canvasHeight) / 2);
|
||||
|
@ -1,217 +1,220 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller");
|
||||
ns.PreviewFilmController = function (framesheet, container, dpi) {
|
||||
var ns = $.namespace("pskl.controller");
|
||||
ns.PreviewFilmController = function (framesheet, container, dpi) {
|
||||
|
||||
this.framesheet = framesheet;
|
||||
this.container = container;
|
||||
this.dpi = this.calculateDPI_();
|
||||
this.framesheet = framesheet;
|
||||
this.container = container;
|
||||
this.dpi = this.calculateDPI_();
|
||||
|
||||
this.redrawFlag = true;
|
||||
this.redrawFlag = true;
|
||||
};
|
||||
|
||||
$.subscribe(Events.TOOL_RELEASED, this.flagForRedraw_.bind(this));
|
||||
$.subscribe(Events.FRAMESHEET_RESET, this.flagForRedraw_.bind(this));
|
||||
$.subscribe(Events.FRAMESHEET_RESET, this.refreshDPI_.bind(this));
|
||||
ns.PreviewFilmController.prototype.init = function() {
|
||||
$.subscribe(Events.TOOL_RELEASED, this.flagForRedraw_.bind(this));
|
||||
$.subscribe(Events.FRAMESHEET_RESET, this.flagForRedraw_.bind(this));
|
||||
$.subscribe(Events.FRAMESHEET_RESET, this.refreshDPI_.bind(this));
|
||||
|
||||
$('#preview-list-scroller').scroll(this.updateScrollerOverflows.bind(this));
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
$('#preview-list-scroller').scroll(this.updateScrollerOverflows.bind(this));
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.init = function() {};
|
||||
ns.PreviewFilmController.prototype.addFrame = function () {
|
||||
this.framesheet.addEmptyFrame();
|
||||
this.framesheet.setCurrentFrameIndex(this.framesheet.getFrameCount() - 1);
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.addFrame = function () {
|
||||
this.framesheet.addEmptyFrame();
|
||||
this.framesheet.setCurrentFrameIndex(this.framesheet.getFrameCount() - 1);
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
ns.PreviewFilmController.prototype.flagForRedraw_ = function () {
|
||||
this.redrawFlag = true;
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.flagForRedraw_ = function () {
|
||||
this.redrawFlag = true;
|
||||
};
|
||||
ns.PreviewFilmController.prototype.refreshDPI_ = function () {
|
||||
this.dpi = this.calculateDPI_();
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.refreshDPI_ = function () {
|
||||
this.dpi = this.calculateDPI_();
|
||||
};
|
||||
ns.PreviewFilmController.prototype.render = function () {
|
||||
if (this.redrawFlag) {
|
||||
// TODO(vincz): Full redraw on any drawing modification, optimize.
|
||||
this.createPreviews_();
|
||||
this.redrawFlag = false;
|
||||
}
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.render = function () {
|
||||
if (this.redrawFlag) {
|
||||
// TODO(vincz): Full redraw on any drawing modification, optimize.
|
||||
this.createPreviews_();
|
||||
this.redrawFlag = false;
|
||||
}
|
||||
};
|
||||
ns.PreviewFilmController.prototype.updateScrollerOverflows = function () {
|
||||
var scroller = $('#preview-list-scroller');
|
||||
var scrollerHeight = scroller.height();
|
||||
var scrollTop = scroller.scrollTop();
|
||||
var scrollerContentHeight = $('#preview-list').height();
|
||||
var treshold = $('.top-overflow').height();
|
||||
var overflowTop = false,
|
||||
overflowBottom = false;
|
||||
if (scrollerHeight < scrollerContentHeight) {
|
||||
if (scrollTop > treshold) {
|
||||
overflowTop = true;
|
||||
}
|
||||
var scrollBottom = (scrollerContentHeight - scrollTop) - scrollerHeight;
|
||||
if (scrollBottom > treshold) {
|
||||
overflowBottom = true;
|
||||
}
|
||||
}
|
||||
var wrapper = $('#preview-list-wrapper');
|
||||
wrapper.toggleClass('top-overflow-visible', overflowTop);
|
||||
wrapper.toggleClass('bottom-overflow-visible', overflowBottom);
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.updateScrollerOverflows = function () {
|
||||
var scroller = $('#preview-list-scroller');
|
||||
var scrollerHeight = scroller.height();
|
||||
var scrollTop = scroller.scrollTop();
|
||||
var scrollerContentHeight = $('#preview-list').height();
|
||||
var treshold = $('.top-overflow').height();
|
||||
var overflowTop = false,
|
||||
overflowBottom = false;
|
||||
if (scrollerHeight < scrollerContentHeight) {
|
||||
if (scrollTop > treshold) {
|
||||
overflowTop = true;
|
||||
}
|
||||
var scrollBottom = (scrollerContentHeight - scrollTop) - scrollerHeight;
|
||||
if (scrollBottom > treshold) {
|
||||
overflowBottom = true;
|
||||
}
|
||||
}
|
||||
var wrapper = $('#preview-list-wrapper');
|
||||
wrapper.toggleClass('top-overflow-visible', overflowTop);
|
||||
wrapper.toggleClass('bottom-overflow-visible', overflowBottom);
|
||||
};
|
||||
ns.PreviewFilmController.prototype.createPreviews_ = function () {
|
||||
|
||||
this.container.html("");
|
||||
// Manually remove tooltips since mouseout events were shortcut by the DOM refresh:
|
||||
$(".tooltip").remove();
|
||||
|
||||
ns.PreviewFilmController.prototype.createPreviews_ = function () {
|
||||
|
||||
this.container.html("");
|
||||
// Manually remove tooltips since mouseout events were shortcut by the DOM refresh:
|
||||
$(".tooltip").remove();
|
||||
var frameCount = this.framesheet.getFrameCount();
|
||||
|
||||
var frameCount = this.framesheet.getFrameCount();
|
||||
for (var i = 0, l = frameCount; i < l ; i++) {
|
||||
this.container.append(this.createPreviewTile_(i));
|
||||
}
|
||||
// Append 'new empty frame' button
|
||||
var newFrameButton = document.createElement("div");
|
||||
newFrameButton.id = "add-frame-action";
|
||||
newFrameButton.className = "add-frame-action";
|
||||
newFrameButton.innerHTML = "<p class='label'>Add new frame</p>";
|
||||
this.container.append(newFrameButton);
|
||||
|
||||
for (var i = 0, l = frameCount; i < l ; i++) {
|
||||
this.container.append(this.createPreviewTile_(i));
|
||||
}
|
||||
// Append 'new empty frame' button
|
||||
var newFrameButton = document.createElement("div");
|
||||
newFrameButton.id = "add-frame-action";
|
||||
newFrameButton.className = "add-frame-action";
|
||||
newFrameButton.innerHTML = "<p class='label'>Add new frame</p>";
|
||||
this.container.append(newFrameButton);
|
||||
$(newFrameButton).click(this.addFrame.bind(this));
|
||||
|
||||
$(newFrameButton).click(this.addFrame.bind(this));
|
||||
|
||||
var needDragndropBehavior = (frameCount > 1);
|
||||
if(needDragndropBehavior) {
|
||||
this.initDragndropBehavior_();
|
||||
}
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
var needDragndropBehavior = (frameCount > 1);
|
||||
if(needDragndropBehavior) {
|
||||
this.initDragndropBehavior_();
|
||||
}
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.PreviewFilmController.prototype.initDragndropBehavior_ = function () {
|
||||
|
||||
$("#preview-list").sortable({
|
||||
placeholder: "preview-tile-drop-proxy",
|
||||
update: $.proxy(this.onUpdate_, this),
|
||||
items: ".preview-tile"
|
||||
});
|
||||
$("#preview-list").disableSelection();
|
||||
};
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.PreviewFilmController.prototype.initDragndropBehavior_ = function () {
|
||||
|
||||
$("#preview-list").sortable({
|
||||
placeholder: "preview-tile-drop-proxy",
|
||||
update: $.proxy(this.onUpdate_, this),
|
||||
items: ".preview-tile"
|
||||
});
|
||||
$("#preview-list").disableSelection();
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.PreviewFilmController.prototype.onUpdate_ = function( event, ui ) {
|
||||
var originFrameId = parseInt(ui.item.data("tile-number"), 10);
|
||||
var targetInsertionId = $('.preview-tile').index(ui.item);
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.PreviewFilmController.prototype.onUpdate_ = function( event, ui ) {
|
||||
var originFrameId = parseInt(ui.item.data("tile-number"), 10);
|
||||
var targetInsertionId = $('.preview-tile').index(ui.item);
|
||||
|
||||
this.framesheet.moveFrame(originFrameId, targetInsertionId);
|
||||
this.framesheet.setCurrentFrameIndex(targetInsertionId);
|
||||
this.framesheet.moveFrame(originFrameId, targetInsertionId);
|
||||
this.framesheet.setCurrentFrameIndex(targetInsertionId);
|
||||
|
||||
// TODO(grosbouddha): move localstorage request to the model layer?
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST);
|
||||
};
|
||||
// TODO(grosbouddha): move localstorage request to the model layer?
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* TODO(vincz): clean this giant rendering function & remove listeners.
|
||||
*/
|
||||
ns.PreviewFilmController.prototype.createPreviewTile_ = function(tileNumber) {
|
||||
var currentFrame = this.framesheet.getFrameByIndex(tileNumber);
|
||||
|
||||
var previewTileRoot = document.createElement("li");
|
||||
var classname = "preview-tile";
|
||||
previewTileRoot.setAttribute("data-tile-number", tileNumber);
|
||||
/**
|
||||
* @private
|
||||
* TODO(vincz): clean this giant rendering function & remove listeners.
|
||||
*/
|
||||
ns.PreviewFilmController.prototype.createPreviewTile_ = function(tileNumber) {
|
||||
var currentFrame = this.framesheet.getFrameByIndex(tileNumber);
|
||||
|
||||
var previewTileRoot = document.createElement("li");
|
||||
var classname = "preview-tile";
|
||||
previewTileRoot.setAttribute("data-tile-number", tileNumber);
|
||||
|
||||
if (this.framesheet.getCurrentFrame() == currentFrame) {
|
||||
classname += " selected";
|
||||
}
|
||||
previewTileRoot.className = classname;
|
||||
if (this.framesheet.getCurrentFrame() == currentFrame) {
|
||||
classname += " selected";
|
||||
}
|
||||
previewTileRoot.className = classname;
|
||||
|
||||
var canvasContainer = document.createElement("div");
|
||||
canvasContainer.className = "canvas-container";
|
||||
|
||||
var canvasBackground = document.createElement("div");
|
||||
canvasBackground.className = "canvas-background";
|
||||
canvasContainer.appendChild(canvasBackground);
|
||||
|
||||
previewTileRoot.addEventListener('click', this.onPreviewClick_.bind(this, tileNumber));
|
||||
var canvasContainer = document.createElement("div");
|
||||
canvasContainer.className = "canvas-container";
|
||||
|
||||
var canvasBackground = document.createElement("div");
|
||||
canvasBackground.className = "canvas-background";
|
||||
canvasContainer.appendChild(canvasBackground);
|
||||
|
||||
previewTileRoot.addEventListener('click', this.onPreviewClick_.bind(this, tileNumber));
|
||||
|
||||
var cloneFrameButton = document.createElement("button");
|
||||
cloneFrameButton.setAttribute('rel', 'tooltip');
|
||||
cloneFrameButton.setAttribute('data-placement', 'right');
|
||||
cloneFrameButton.setAttribute('title', 'Duplicate this frame');
|
||||
cloneFrameButton.className = "tile-overlay duplicate-frame-action";
|
||||
previewTileRoot.appendChild(cloneFrameButton);
|
||||
cloneFrameButton.addEventListener('click', this.onAddButtonClick_.bind(this, tileNumber));
|
||||
var cloneFrameButton = document.createElement("button");
|
||||
cloneFrameButton.setAttribute('rel', 'tooltip');
|
||||
cloneFrameButton.setAttribute('data-placement', 'right');
|
||||
cloneFrameButton.setAttribute('title', 'Duplicate this frame');
|
||||
cloneFrameButton.className = "tile-overlay duplicate-frame-action";
|
||||
previewTileRoot.appendChild(cloneFrameButton);
|
||||
cloneFrameButton.addEventListener('click', this.onAddButtonClick_.bind(this, tileNumber));
|
||||
|
||||
// TODO(vincz): Eventually optimize this part by not recreating a FrameRenderer. Note that the real optim
|
||||
// is to make this update function (#createPreviewTile) less aggressive.
|
||||
var renderingOptions = {"dpi": this.dpi };
|
||||
var currentFrameRenderer = new pskl.rendering.FrameRenderer($(canvasContainer), renderingOptions, "tile-view");
|
||||
currentFrameRenderer.init(currentFrame);
|
||||
|
||||
previewTileRoot.appendChild(canvasContainer);
|
||||
// TODO(vincz): Eventually optimize this part by not recreating a FrameRenderer. Note that the real optim
|
||||
// is to make this update function (#createPreviewTile) less aggressive.
|
||||
var renderingOptions = {"dpi": this.dpi };
|
||||
var currentFrameRenderer = new pskl.rendering.FrameRenderer($(canvasContainer), renderingOptions, "tile-view");
|
||||
currentFrameRenderer.render(currentFrame);
|
||||
|
||||
previewTileRoot.appendChild(canvasContainer);
|
||||
|
||||
if(tileNumber > 0 || this.framesheet.getFrameCount() > 1) {
|
||||
// Add 'remove frame' button.
|
||||
var deleteButton = document.createElement("button");
|
||||
deleteButton.setAttribute('rel', 'tooltip');
|
||||
deleteButton.setAttribute('data-placement', 'right');
|
||||
deleteButton.setAttribute('title', 'Delete this frame');
|
||||
deleteButton.className = "tile-overlay delete-frame-action";
|
||||
deleteButton.addEventListener('click', this.onDeleteButtonClick_.bind(this, tileNumber));
|
||||
previewTileRoot.appendChild(deleteButton);
|
||||
if(tileNumber > 0 || this.framesheet.getFrameCount() > 1) {
|
||||
// Add 'remove frame' button.
|
||||
var deleteButton = document.createElement("button");
|
||||
deleteButton.setAttribute('rel', 'tooltip');
|
||||
deleteButton.setAttribute('data-placement', 'right');
|
||||
deleteButton.setAttribute('title', 'Delete this frame');
|
||||
deleteButton.className = "tile-overlay delete-frame-action";
|
||||
deleteButton.addEventListener('click', this.onDeleteButtonClick_.bind(this, tileNumber));
|
||||
previewTileRoot.appendChild(deleteButton);
|
||||
|
||||
// Add 'dragndrop handle'.
|
||||
var dndHandle = document.createElement("div");
|
||||
dndHandle.className = "tile-overlay dnd-action";
|
||||
previewTileRoot.appendChild(dndHandle);
|
||||
}
|
||||
var tileCount = document.createElement("div");
|
||||
tileCount.className = "tile-overlay tile-count";
|
||||
tileCount.innerHTML = tileNumber;
|
||||
previewTileRoot.appendChild(tileCount);
|
||||
|
||||
// Add 'dragndrop handle'.
|
||||
var dndHandle = document.createElement("div");
|
||||
dndHandle.className = "tile-overlay dnd-action";
|
||||
previewTileRoot.appendChild(dndHandle);
|
||||
}
|
||||
var tileCount = document.createElement("div");
|
||||
tileCount.className = "tile-overlay tile-count";
|
||||
tileCount.innerHTML = tileNumber;
|
||||
previewTileRoot.appendChild(tileCount);
|
||||
|
||||
|
||||
return previewTileRoot;
|
||||
};
|
||||
return previewTileRoot;
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.onPreviewClick_ = function (index, evt) {
|
||||
// has not class tile-action:
|
||||
if(!evt.target.classList.contains('tile-overlay')) {
|
||||
this.framesheet.setCurrentFrameIndex(index);
|
||||
}
|
||||
};
|
||||
ns.PreviewFilmController.prototype.onPreviewClick_ = function (index, evt) {
|
||||
// has not class tile-action:
|
||||
if(!evt.target.classList.contains('tile-overlay')) {
|
||||
this.framesheet.setCurrentFrameIndex(index);
|
||||
}
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.onDeleteButtonClick_ = function (index, evt) {
|
||||
this.framesheet.removeFrameByIndex(index);
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
ns.PreviewFilmController.prototype.onDeleteButtonClick_ = function (index, evt) {
|
||||
this.framesheet.removeFrameByIndex(index);
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.onAddButtonClick_ = function (index, evt) {
|
||||
this.framesheet.duplicateFrameByIndex(index);
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model
|
||||
this.framesheet.setCurrentFrameIndex(index + 1);
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
ns.PreviewFilmController.prototype.onAddButtonClick_ = function (index, evt) {
|
||||
this.framesheet.duplicateFrameByIndex(index);
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model
|
||||
this.framesheet.setCurrentFrameIndex(index + 1);
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the preview DPI depending on the framesheet size
|
||||
*/
|
||||
ns.PreviewFilmController.prototype.calculateDPI_ = function () {
|
||||
var previewSize = 120,
|
||||
framePixelHeight = this.framesheet.getCurrentFrame().getHeight(),
|
||||
framePixelWidth = this.framesheet.getCurrentFrame().getWidth();
|
||||
// TODO (julz) : should have a utility to get a Size from framesheet easily (what about empty framesheets though ?)
|
||||
/**
|
||||
* Calculate the preview DPI depending on the framesheet size
|
||||
*/
|
||||
ns.PreviewFilmController.prototype.calculateDPI_ = function () {
|
||||
var curFrame = this.framesheet.getCurrentFrame(),
|
||||
frameHeight = curFrame.getHeight(),
|
||||
frameWidth = curFrame.getWidth(),
|
||||
maxFrameDim = Math.max(frameWidth, frameHeight);
|
||||
|
||||
return pskl.PixelUtils.calculateDPI(previewSize, previewSize, framePixelHeight, framePixelWidth);
|
||||
};
|
||||
var previewHeight = Constants.PREVIEW_FILM_SIZE * frameHeight / maxFrameDim;
|
||||
var previewWidth = Constants.PREVIEW_FILM_SIZE * frameWidth / maxFrameDim;
|
||||
|
||||
return pskl.PixelUtils.calculateDPI(previewHeight, previewWidth, frameHeight, frameWidth) || 1;
|
||||
};
|
||||
})();
|
@ -1,45 +1,45 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller");
|
||||
var ns = $.namespace("pskl.controller");
|
||||
|
||||
ns.SettingsController = function () {};
|
||||
ns.SettingsController = function () {};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.SettingsController.prototype.init = function() {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.SettingsController.prototype.init = function() {
|
||||
|
||||
// Highlight selected background picker:
|
||||
var backgroundClass = pskl.UserSettings.get(pskl.UserSettings.CANVAS_BACKGROUND);
|
||||
$('#background-picker-wrapper')
|
||||
.find('.background-picker[data-background-class=' + backgroundClass + ']')
|
||||
.addClass('selected');
|
||||
// Highlight selected background picker:
|
||||
var backgroundClass = pskl.UserSettings.get(pskl.UserSettings.CANVAS_BACKGROUND);
|
||||
$('#background-picker-wrapper')
|
||||
.find('.background-picker[data-background-class=' + backgroundClass + ']')
|
||||
.addClass('selected');
|
||||
|
||||
// Initial state for grid display:
|
||||
var show_grid = pskl.UserSettings.get(pskl.UserSettings.SHOW_GRID);
|
||||
$('#show-grid').prop('checked', show_grid);
|
||||
// Initial state for grid display:
|
||||
var show_grid = pskl.UserSettings.get(pskl.UserSettings.SHOW_GRID);
|
||||
$('#show-grid').prop('checked', show_grid);
|
||||
|
||||
// Expand drawer when clicking 'Settings' tab.
|
||||
$('#settings').click(function(evt) {
|
||||
$('.right-sticky-section').toggleClass('expanded');
|
||||
$('#settings').toggleClass('has-expanded-drawer');
|
||||
});
|
||||
// Expand drawer when clicking 'Settings' tab.
|
||||
$('#settings').click(function(evt) {
|
||||
$('.right-sticky-section').toggleClass('expanded');
|
||||
$('#settings').toggleClass('has-expanded-drawer');
|
||||
});
|
||||
|
||||
// Handle grid display changes:
|
||||
$('#show-grid').change($.proxy(function(evt) {
|
||||
var checked = $('#show-grid').prop('checked');
|
||||
pskl.UserSettings.set(pskl.UserSettings.SHOW_GRID, checked);
|
||||
}, this));
|
||||
// Handle grid display changes:
|
||||
$('#show-grid').change($.proxy(function(evt) {
|
||||
var checked = $('#show-grid').prop('checked');
|
||||
pskl.UserSettings.set(pskl.UserSettings.SHOW_GRID, checked);
|
||||
}, this));
|
||||
|
||||
// Handle canvas background changes:
|
||||
$('#background-picker-wrapper').click(function(evt) {
|
||||
var target = $(evt.target).closest('.background-picker');
|
||||
if (target.length) {
|
||||
var backgroundClass = target.data('background-class');
|
||||
pskl.UserSettings.set(pskl.UserSettings.CANVAS_BACKGROUND, backgroundClass);
|
||||
// Handle canvas background changes:
|
||||
$('#background-picker-wrapper').click(function(evt) {
|
||||
var target = $(evt.target).closest('.background-picker');
|
||||
if (target.length) {
|
||||
var backgroundClass = target.data('background-class');
|
||||
pskl.UserSettings.set(pskl.UserSettings.CANVAS_BACKGROUND, backgroundClass);
|
||||
|
||||
$('.background-picker').removeClass('selected');
|
||||
target.addClass('selected');
|
||||
}
|
||||
});
|
||||
};
|
||||
$('.background-picker').removeClass('selected');
|
||||
target.addClass('selected');
|
||||
}
|
||||
});
|
||||
};
|
||||
})();
|
@ -1,99 +1,107 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller");
|
||||
var ns = $.namespace("pskl.controller");
|
||||
|
||||
|
||||
ns.ToolController = function () {
|
||||
|
||||
this.toolInstances = {
|
||||
"simplePen" : new pskl.drawingtools.SimplePen(),
|
||||
"verticalMirrorPen" : new pskl.drawingtools.VerticalMirrorPen(),
|
||||
"eraser" : new pskl.drawingtools.Eraser(),
|
||||
"paintBucket" : new pskl.drawingtools.PaintBucket(),
|
||||
"stroke" : new pskl.drawingtools.Stroke(),
|
||||
"rectangle" : new pskl.drawingtools.Rectangle(),
|
||||
"circle" : new pskl.drawingtools.Circle(),
|
||||
"move" : new pskl.drawingtools.Move(),
|
||||
"rectangleSelect" : new pskl.drawingtools.RectangleSelect(),
|
||||
"shapeSelect" : new pskl.drawingtools.ShapeSelect(),
|
||||
"colorPicker" : new pskl.drawingtools.ColorPicker()
|
||||
};
|
||||
|
||||
this.currentSelectedTool = this.toolInstances.simplePen;
|
||||
this.previousSelectedTool = this.toolInstances.simplePen;
|
||||
|
||||
ns.ToolController = function () {
|
||||
|
||||
this.toolInstances = {
|
||||
"simplePen" : new pskl.drawingtools.SimplePen(),
|
||||
"verticalMirrorPen" : new pskl.drawingtools.VerticalMirrorPen(),
|
||||
"eraser" : new pskl.drawingtools.Eraser(),
|
||||
"paintBucket" : new pskl.drawingtools.PaintBucket(),
|
||||
"stroke" : new pskl.drawingtools.Stroke(),
|
||||
"rectangle" : new pskl.drawingtools.Rectangle(),
|
||||
"circle" : new pskl.drawingtools.Circle(),
|
||||
"move" : new pskl.drawingtools.Move(),
|
||||
"rectangleSelect" : new pskl.drawingtools.RectangleSelect(),
|
||||
"shapeSelect" : new pskl.drawingtools.ShapeSelect(),
|
||||
"colorPicker" : new pskl.drawingtools.ColorPicker()
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.ToolController.prototype.activateToolOnStage_ = function(tool) {
|
||||
var stage = $("body");
|
||||
var previousSelectedToolClass = stage.data("selected-tool-class");
|
||||
if(previousSelectedToolClass) {
|
||||
stage.removeClass(previousSelectedToolClass);
|
||||
}
|
||||
stage.addClass(tool.toolId);
|
||||
stage.data("selected-tool-class", tool.toolId);
|
||||
};
|
||||
this.currentSelectedTool = this.toolInstances.simplePen;
|
||||
this.previousSelectedTool = this.toolInstances.simplePen;
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.ToolController.prototype.selectTool_ = function(tool) {
|
||||
console.log("Selecting Tool:" , this.currentSelectedTool);
|
||||
this.currentSelectedTool = tool;
|
||||
this.activateToolOnStage_(this.currentSelectedTool);
|
||||
$.publish(Events.TOOL_SELECTED, [tool]);
|
||||
};
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.ToolController.prototype.init = function() {
|
||||
this.createToolMarkup_();
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.ToolController.prototype.onToolIconClicked_ = function(evt) {
|
||||
var target = $(evt.target);
|
||||
var clickedTool = target.closest(".tool-icon");
|
||||
// Initialize tool:
|
||||
// Set SimplePen as default selected tool:
|
||||
this.selectTool_(this.toolInstances.simplePen);
|
||||
// Activate listener on tool panel:
|
||||
$("#tool-section").click($.proxy(this.onToolIconClicked_, this));
|
||||
};
|
||||
|
||||
if(clickedTool.length) {
|
||||
for(var tool in this.toolInstances) {
|
||||
if (this.toolInstances[tool].toolId == clickedTool.data().toolId) {
|
||||
this.selectTool_(this.toolInstances[tool]);
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.ToolController.prototype.activateToolOnStage_ = function(tool) {
|
||||
var stage = $("body");
|
||||
var previousSelectedToolClass = stage.data("selected-tool-class");
|
||||
if(previousSelectedToolClass) {
|
||||
stage.removeClass(previousSelectedToolClass);
|
||||
}
|
||||
stage.addClass(tool.toolId);
|
||||
stage.data("selected-tool-class", tool.toolId);
|
||||
};
|
||||
|
||||
// Show tool as selected:
|
||||
$('#tool-section .tool-icon.selected').removeClass('selected');
|
||||
clickedTool.addClass('selected');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.ToolController.prototype.selectTool_ = function(tool) {
|
||||
console.log("Selecting Tool:" , this.currentSelectedTool);
|
||||
this.currentSelectedTool = tool;
|
||||
this.activateToolOnStage_(this.currentSelectedTool);
|
||||
$.publish(Events.TOOL_SELECTED, [tool]);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.ToolController.prototype.createToolMarkup_ = function() {
|
||||
var currentTool, toolMarkup = '', extraClass;
|
||||
// TODO(vincz): Tools rendering order is not enforced by the data stucture (this.toolInstances), fix that.
|
||||
for (var toolKey in this.toolInstances) {
|
||||
currentTool = this.toolInstances[toolKey];
|
||||
extraClass = currentTool.toolId;
|
||||
if (this.currentSelectedTool == currentTool) {
|
||||
extraClass = extraClass + " selected";
|
||||
}
|
||||
toolMarkup += '<li rel="tooltip" data-placement="right" class="tool-icon ' + extraClass + '" data-tool-id="' + currentTool.toolId +
|
||||
'" title="' + currentTool.helpText + '"></li>';
|
||||
}
|
||||
$('#tools-container').html(toolMarkup);
|
||||
};
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.ToolController.prototype.onToolIconClicked_ = function(evt) {
|
||||
var target = $(evt.target);
|
||||
var clickedTool = target.closest(".tool-icon");
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.ToolController.prototype.init = function() {
|
||||
if(clickedTool.length) {
|
||||
var toolId = clickedTool.data().toolId;
|
||||
var tool = this.getToolById_(toolId);
|
||||
if (tool) {
|
||||
this.selectTool_(tool);
|
||||
|
||||
this.createToolMarkup_();
|
||||
// Show tool as selected:
|
||||
$('#tool-section .tool-icon.selected').removeClass('selected');
|
||||
clickedTool.addClass('selected');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize tool:
|
||||
// Set SimplePen as default selected tool:
|
||||
this.selectTool_(this.toolInstances.simplePen);
|
||||
// Activate listener on tool panel:
|
||||
$("#tool-section").click($.proxy(this.onToolIconClicked_, this));
|
||||
};
|
||||
ns.ToolController.prototype.getToolById_ = function (toolId) {
|
||||
for(var key in this.toolInstances) {
|
||||
if (this.toolInstances[key].toolId == toolId) {
|
||||
return this.toolInstances[key];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.ToolController.prototype.createToolMarkup_ = function() {
|
||||
var currentTool, toolMarkup = '', extraClass;
|
||||
// TODO(vincz): Tools rendering order is not enforced by the data stucture (this.toolInstances), fix that.
|
||||
for (var toolKey in this.toolInstances) {
|
||||
currentTool = this.toolInstances[toolKey];
|
||||
extraClass = currentTool.toolId;
|
||||
if (this.currentSelectedTool == currentTool) {
|
||||
extraClass = extraClass + " selected";
|
||||
}
|
||||
toolMarkup += '<li rel="tooltip" data-placement="right" class="tool-icon ' + extraClass + '" data-tool-id="' + currentTool.toolId +
|
||||
'" title="' + currentTool.helpText + '"></li>';
|
||||
}
|
||||
$('#tools-container').html(toolMarkup);
|
||||
};
|
||||
})();
|
@ -4,69 +4,69 @@
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.BaseTool = function() {};
|
||||
ns.BaseTool = function() {};
|
||||
|
||||
ns.BaseTool.prototype.applyToolAt = function(col, row, color, frame, overlay) {};
|
||||
|
||||
ns.BaseTool.prototype.moveToolAt = function(col, row, color, frame, overlay) {};
|
||||
ns.BaseTool.prototype.applyToolAt = function(col, row, color, frame, overlay) {};
|
||||
|
||||
ns.BaseTool.prototype.moveToolAt = function(col, row, color, frame, overlay) {};
|
||||
|
||||
ns.BaseTool.prototype.moveUnactiveToolAt = function(col, row, color, frame, overlay) {
|
||||
if (overlay.containsPixel(col, row)) {
|
||||
if (!isNaN(this.highlightedPixelCol) &&
|
||||
!isNaN(this.highlightedPixelRow) &&
|
||||
(this.highlightedPixelRow != row ||
|
||||
this.highlightedPixelCol != col)) {
|
||||
ns.BaseTool.prototype.moveUnactiveToolAt = function(col, row, color, frame, overlay) {
|
||||
if (overlay.containsPixel(col, row)) {
|
||||
if (!isNaN(this.highlightedPixelCol) &&
|
||||
!isNaN(this.highlightedPixelRow) &&
|
||||
(this.highlightedPixelRow != row ||
|
||||
this.highlightedPixelCol != col)) {
|
||||
|
||||
// Clean the previously highlighted pixel:
|
||||
overlay.clear();
|
||||
}
|
||||
// Clean the previously highlighted pixel:
|
||||
overlay.clear();
|
||||
}
|
||||
|
||||
// Show the current pixel targeted by the tool:
|
||||
overlay.setPixel(col, row, Constants.TOOL_TARGET_HIGHLIGHT_COLOR);
|
||||
// Show the current pixel targeted by the tool:
|
||||
overlay.setPixel(col, row, Constants.TOOL_TARGET_HIGHLIGHT_COLOR);
|
||||
|
||||
this.highlightedPixelCol = col;
|
||||
this.highlightedPixelRow = row;
|
||||
}
|
||||
};
|
||||
this.highlightedPixelCol = col;
|
||||
this.highlightedPixelRow = row;
|
||||
}
|
||||
};
|
||||
|
||||
ns.BaseTool.prototype.releaseToolAt = function(col, row, color, frame, overlay) {};
|
||||
ns.BaseTool.prototype.releaseToolAt = function(col, row, color, frame, overlay) {};
|
||||
|
||||
/**
|
||||
* Bresenham line algorihtm: Get an array of pixels from
|
||||
* start and end coordinates.
|
||||
*
|
||||
* http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
|
||||
* http://stackoverflow.com/questions/4672279/bresenham-algorithm-in-javascript
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
ns.BaseTool.prototype.getLinePixels_ = function(x0, x1, y0, y1) {
|
||||
|
||||
var pixels = [];
|
||||
var dx = Math.abs(x1-x0);
|
||||
var dy = Math.abs(y1-y0);
|
||||
var sx = (x0 < x1) ? 1 : -1;
|
||||
var sy = (y0 < y1) ? 1 : -1;
|
||||
var err = dx-dy;
|
||||
/**
|
||||
* Bresenham line algorihtm: Get an array of pixels from
|
||||
* start and end coordinates.
|
||||
*
|
||||
* http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
|
||||
* http://stackoverflow.com/questions/4672279/bresenham-algorithm-in-javascript
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
ns.BaseTool.prototype.getLinePixels_ = function(x0, x1, y0, y1) {
|
||||
|
||||
var pixels = [];
|
||||
var dx = Math.abs(x1-x0);
|
||||
var dy = Math.abs(y1-y0);
|
||||
var sx = (x0 < x1) ? 1 : -1;
|
||||
var sy = (y0 < y1) ? 1 : -1;
|
||||
var err = dx-dy;
|
||||
|
||||
while(true){
|
||||
while(true){
|
||||
|
||||
// Do what you need to for this
|
||||
pixels.push({"col": x0, "row": y0});
|
||||
// Do what you need to for this
|
||||
pixels.push({"col": x0, "row": y0});
|
||||
|
||||
if ((x0==x1) && (y0==y1)) break;
|
||||
var e2 = 2*err;
|
||||
if (e2>-dy){
|
||||
err -= dy;
|
||||
x0 += sx;
|
||||
}
|
||||
if (e2 < dx) {
|
||||
err += dx;
|
||||
y0 += sy;
|
||||
}
|
||||
}
|
||||
return pixels;
|
||||
};
|
||||
if ((x0==x1) && (y0==y1)) break;
|
||||
var e2 = 2*err;
|
||||
if (e2>-dy){
|
||||
err -= dy;
|
||||
x0 += sx;
|
||||
}
|
||||
if (e2 < dx) {
|
||||
err += dx;
|
||||
y0 += sy;
|
||||
}
|
||||
}
|
||||
return pixels;
|
||||
};
|
||||
})();
|
||||
|
@ -4,82 +4,82 @@
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.Circle = function() {
|
||||
this.toolId = "tool-circle";
|
||||
this.helpText = "Circle tool";
|
||||
|
||||
// Circle's first point coordinates (set in applyToolAt)
|
||||
this.startCol = null;
|
||||
this.startRow = null;
|
||||
};
|
||||
ns.Circle = function() {
|
||||
this.toolId = "tool-circle";
|
||||
this.helpText = "Circle tool";
|
||||
|
||||
// Circle's first point coordinates (set in applyToolAt)
|
||||
this.startCol = null;
|
||||
this.startRow = null;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.Circle, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Circle.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.startCol = col;
|
||||
this.startRow = row;
|
||||
|
||||
// Drawing the first point of the rectangle in the fake overlay canvas:
|
||||
overlay.setPixel(col, row, color);
|
||||
};
|
||||
pskl.utils.inherit(ns.Circle, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Circle.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.startCol = col;
|
||||
this.startRow = row;
|
||||
|
||||
// Drawing the first point of the rectangle in the fake overlay canvas:
|
||||
overlay.setPixel(col, row, color);
|
||||
};
|
||||
|
||||
ns.Circle.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
if(color == Constants.TRANSPARENT_COLOR) {
|
||||
color = Constants.SELECTION_TRANSPARENT_COLOR;
|
||||
}
|
||||
ns.Circle.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
if(color == Constants.TRANSPARENT_COLOR) {
|
||||
color = Constants.SELECTION_TRANSPARENT_COLOR;
|
||||
}
|
||||
|
||||
// draw in overlay
|
||||
this.drawCircle_(col, row, color, overlay);
|
||||
};
|
||||
// draw in overlay
|
||||
this.drawCircle_(col, row, color, overlay);
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Circle.prototype.releaseToolAt = function(col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
if(frame.containsPixel(col, row)) { // cancel if outside of canvas
|
||||
// draw in frame to finalize
|
||||
this.drawCircle_(col, row, color, frame);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Circle.prototype.releaseToolAt = function(col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
if(frame.containsPixel(col, row)) { // cancel if outside of canvas
|
||||
// draw in frame to finalize
|
||||
this.drawCircle_(col, row, color, frame);
|
||||
}
|
||||
};
|
||||
|
||||
ns.Circle.prototype.drawCircle_ = function (col, row, color, targetFrame) {
|
||||
var circlePoints = this.getCirclePixels_(this.startCol, this.startRow, col, row);
|
||||
for(var i = 0; i< circlePoints.length; i++) {
|
||||
// Change model:
|
||||
targetFrame.setPixel(circlePoints[i].col, circlePoints[i].row, color);
|
||||
}
|
||||
};
|
||||
ns.Circle.prototype.drawCircle_ = function (col, row, color, targetFrame) {
|
||||
var circlePoints = this.getCirclePixels_(this.startCol, this.startRow, col, row);
|
||||
for(var i = 0; i< circlePoints.length; i++) {
|
||||
// Change model:
|
||||
targetFrame.setPixel(circlePoints[i].col, circlePoints[i].row, color);
|
||||
}
|
||||
};
|
||||
|
||||
ns.Circle.prototype.getCirclePixels_ = function (x0, y0, x1, y1) {
|
||||
var coords = pskl.PixelUtils.getOrderedRectangleCoordinates(x0, y0, x1, y1);
|
||||
var xC = (coords.x0 + coords.x1)/2;
|
||||
var yC = (coords.y0 + coords.y1)/2;
|
||||
|
||||
var rX = coords.x1 - xC;
|
||||
var rY = coords.y1 - yC;
|
||||
ns.Circle.prototype.getCirclePixels_ = function (x0, y0, x1, y1) {
|
||||
var coords = pskl.PixelUtils.getOrderedRectangleCoordinates(x0, y0, x1, y1);
|
||||
var xC = (coords.x0 + coords.x1)/2;
|
||||
var yC = (coords.y0 + coords.y1)/2;
|
||||
|
||||
var rX = coords.x1 - xC;
|
||||
var rY = coords.y1 - yC;
|
||||
|
||||
var pixels = [];
|
||||
var x, y, angle;
|
||||
for (x = coords.x0 ; x < coords.x1 ; x++) {
|
||||
angle = Math.acos((x - xC)/rX);
|
||||
y = Math.round(rY * Math.sin(angle) + yC);
|
||||
pixels.push({"col": x, "row": y});
|
||||
pixels.push({"col": 2*xC - x, "row": 2*yC - y});
|
||||
}
|
||||
var pixels = [];
|
||||
var x, y, angle;
|
||||
for (x = coords.x0 ; x < coords.x1 ; x++) {
|
||||
angle = Math.acos((x - xC)/rX);
|
||||
y = Math.round(rY * Math.sin(angle) + yC);
|
||||
pixels.push({"col": x, "row": y});
|
||||
pixels.push({"col": 2*xC - x, "row": 2*yC - y});
|
||||
}
|
||||
|
||||
for (y = coords.y0 ; y < coords.y1 ; y++) {
|
||||
angle = Math.asin((y - yC)/rY);
|
||||
x = Math.round(rX * Math.cos(angle) + xC);
|
||||
pixels.push({"col": x, "row": y});
|
||||
pixels.push({"col": 2*xC - x, "row": 2*yC - y});
|
||||
}
|
||||
return pixels;
|
||||
};
|
||||
for (y = coords.y0 ; y < coords.y1 ; y++) {
|
||||
angle = Math.asin((y - yC)/rY);
|
||||
x = Math.round(rX * Math.cos(angle) + xC);
|
||||
pixels.push({"col": x, "row": y});
|
||||
pixels.push({"col": 2*xC - x, "row": 2*yC - y});
|
||||
}
|
||||
return pixels;
|
||||
};
|
||||
})();
|
||||
|
@ -4,26 +4,26 @@
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.ColorPicker = function() {
|
||||
this.toolId = "tool-colorpicker";
|
||||
this.helpText = "Color picker";
|
||||
};
|
||||
ns.ColorPicker = function() {
|
||||
this.toolId = "tool-colorpicker";
|
||||
this.helpText = "Color picker";
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.ColorPicker, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.ColorPicker.prototype.applyToolAt = function(col, row, color, frame, overlay, context) {
|
||||
if (frame.containsPixel(col, row)) {
|
||||
var sampledColor = frame.getPixel(col, row);
|
||||
if (context.button == Constants.LEFT_BUTTON) {
|
||||
$.publish(Events.PRIMARY_COLOR_SELECTED, [sampledColor]);
|
||||
} else if (context.button == Constants.RIGHT_BUTTON) {
|
||||
$.publish(Events.SECONDARY_COLOR_SELECTED, [sampledColor]);
|
||||
}
|
||||
}
|
||||
};
|
||||
pskl.utils.inherit(ns.ColorPicker, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.ColorPicker.prototype.applyToolAt = function(col, row, color, frame, overlay, context) {
|
||||
if (frame.containsPixel(col, row)) {
|
||||
var sampledColor = frame.getPixel(col, row);
|
||||
if (context.button == Constants.LEFT_BUTTON) {
|
||||
$.publish(Events.PRIMARY_COLOR_SELECTED, [sampledColor]);
|
||||
} else if (context.button == Constants.RIGHT_BUTTON) {
|
||||
$.publish(Events.SECONDARY_COLOR_SELECTED, [sampledColor]);
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
@ -4,20 +4,20 @@
|
||||
* @require Constants
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.Eraser = function() {
|
||||
this.toolId = "tool-eraser";
|
||||
this.helpText = "Eraser tool";
|
||||
};
|
||||
ns.Eraser = function() {
|
||||
this.toolId = "tool-eraser";
|
||||
this.helpText = "Eraser tool";
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.Eraser, ns.SimplePen);
|
||||
pskl.utils.inherit(ns.Eraser, ns.SimplePen);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Eraser.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.superclass.applyToolAt.call(this, col, row, Constants.TRANSPARENT_COLOR, frame, overlay);
|
||||
};
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Eraser.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.superclass.applyToolAt.call(this, col, row, Constants.TRANSPARENT_COLOR, frame, overlay);
|
||||
};
|
||||
})();
|
@ -4,51 +4,51 @@
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.Move = function() {
|
||||
this.toolId = "tool-move";
|
||||
this.helpText = "Move tool";
|
||||
|
||||
// Stroke's first point coordinates (set in applyToolAt)
|
||||
this.startCol = null;
|
||||
this.startRow = null;
|
||||
};
|
||||
ns.Move = function() {
|
||||
this.toolId = "tool-move";
|
||||
this.helpText = "Move tool";
|
||||
|
||||
// Stroke's first point coordinates (set in applyToolAt)
|
||||
this.startCol = null;
|
||||
this.startRow = null;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.Move, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Move.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.startCol = col;
|
||||
this.startRow = row;
|
||||
this.frameClone = frame.clone();
|
||||
};
|
||||
pskl.utils.inherit(ns.Move, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Move.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.startCol = col;
|
||||
this.startRow = row;
|
||||
this.frameClone = frame.clone();
|
||||
};
|
||||
|
||||
ns.Move.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
var colDiff = col - this.startCol, rowDiff = row - this.startRow;
|
||||
this.shiftFrame(colDiff, rowDiff, frame, this.frameClone);
|
||||
};
|
||||
ns.Move.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
var colDiff = col - this.startCol, rowDiff = row - this.startRow;
|
||||
this.shiftFrame(colDiff, rowDiff, frame, this.frameClone);
|
||||
};
|
||||
|
||||
ns.Move.prototype.shiftFrame = function (colDiff, rowDiff, frame, reference) {
|
||||
var color;
|
||||
for (var col = 0 ; col < frame.getWidth() ; col++) {
|
||||
for (var row = 0 ; row < frame.getHeight() ; row++) {
|
||||
if (reference.containsPixel(col - colDiff, row - rowDiff)) {
|
||||
color = reference.getPixel(col - colDiff, row - rowDiff);
|
||||
} else {
|
||||
color = Constants.TRANSPARENT_COLOR;
|
||||
}
|
||||
frame.setPixel(col, row, color);
|
||||
}
|
||||
}
|
||||
};
|
||||
ns.Move.prototype.shiftFrame = function (colDiff, rowDiff, frame, reference) {
|
||||
var color;
|
||||
for (var col = 0 ; col < frame.getWidth() ; col++) {
|
||||
for (var row = 0 ; row < frame.getHeight() ; row++) {
|
||||
if (reference.containsPixel(col - colDiff, row - rowDiff)) {
|
||||
color = reference.getPixel(col - colDiff, row - rowDiff);
|
||||
} else {
|
||||
color = Constants.TRANSPARENT_COLOR;
|
||||
}
|
||||
frame.setPixel(col, row, color);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Move.prototype.releaseToolAt = function(col, row, color, frame, overlay) {
|
||||
this.moveToolAt(col, row, color, frame, overlay);
|
||||
};
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Move.prototype.releaseToolAt = function(col, row, color, frame, overlay) {
|
||||
this.moveToolAt(col, row, color, frame, overlay);
|
||||
};
|
||||
})();
|
||||
|
@ -4,22 +4,22 @@
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.PaintBucket = function() {
|
||||
this.toolId = "tool-paint-bucket";
|
||||
this.helpText = "Paint bucket tool";
|
||||
};
|
||||
ns.PaintBucket = function() {
|
||||
this.toolId = "tool-paint-bucket";
|
||||
this.helpText = "Paint bucket tool";
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.PaintBucket, ns.BaseTool);
|
||||
pskl.utils.inherit(ns.PaintBucket, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.PaintBucket.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.PaintBucket.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
|
||||
pskl.PixelUtils.paintSimilarConnectedPixelsFromFrame(frame, col, row, color);
|
||||
};
|
||||
pskl.PixelUtils.paintSimilarConnectedPixelsFromFrame(frame, col, row, color);
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
|
@ -4,56 +4,56 @@
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.Rectangle = function() {
|
||||
this.toolId = "tool-rectangle";
|
||||
this.helpText = "Rectangle tool";
|
||||
|
||||
// Rectangle's first point coordinates (set in applyToolAt)
|
||||
this.startCol = null;
|
||||
this.startRow = null;
|
||||
};
|
||||
ns.Rectangle = function() {
|
||||
this.toolId = "tool-rectangle";
|
||||
this.helpText = "Rectangle tool";
|
||||
|
||||
// Rectangle's first point coordinates (set in applyToolAt)
|
||||
this.startCol = null;
|
||||
this.startRow = null;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.Rectangle, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Rectangle.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.startCol = col;
|
||||
this.startRow = row;
|
||||
|
||||
// Drawing the first point of the rectangle in the fake overlay canvas:
|
||||
overlay.setPixel(col, row, color);
|
||||
};
|
||||
pskl.utils.inherit(ns.Rectangle, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Rectangle.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.startCol = col;
|
||||
this.startRow = row;
|
||||
|
||||
// Drawing the first point of the rectangle in the fake overlay canvas:
|
||||
overlay.setPixel(col, row, color);
|
||||
};
|
||||
|
||||
ns.Rectangle.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
if(color == Constants.TRANSPARENT_COLOR) {
|
||||
color = Constants.SELECTION_TRANSPARENT_COLOR;
|
||||
}
|
||||
ns.Rectangle.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
if(color == Constants.TRANSPARENT_COLOR) {
|
||||
color = Constants.SELECTION_TRANSPARENT_COLOR;
|
||||
}
|
||||
|
||||
// draw in overlay
|
||||
this.drawRectangle_(col, row, color, overlay);
|
||||
};
|
||||
// draw in overlay
|
||||
this.drawRectangle_(col, row, color, overlay);
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Rectangle.prototype.releaseToolAt = function(col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
if(frame.containsPixel(col, row)) { // cancel if outside of canvas
|
||||
// draw in frame to finalize
|
||||
this.drawRectangle_(col, row, color, frame);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Rectangle.prototype.releaseToolAt = function(col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
if(frame.containsPixel(col, row)) { // cancel if outside of canvas
|
||||
// draw in frame to finalize
|
||||
this.drawRectangle_(col, row, color, frame);
|
||||
}
|
||||
};
|
||||
|
||||
ns.Rectangle.prototype.drawRectangle_ = function (col, row, color, targetFrame) {
|
||||
var strokePoints = pskl.PixelUtils.getBoundRectanglePixels(this.startCol, this.startRow, col, row);
|
||||
for(var i = 0; i< strokePoints.length; i++) {
|
||||
// Change model:
|
||||
targetFrame.setPixel(strokePoints[i].col, strokePoints[i].row, color);
|
||||
}
|
||||
};
|
||||
ns.Rectangle.prototype.drawRectangle_ = function (col, row, color, targetFrame) {
|
||||
var strokePoints = pskl.PixelUtils.getBoundRectanglePixels(this.startCol, this.startRow, col, row);
|
||||
for(var i = 0; i< strokePoints.length; i++) {
|
||||
// Change model:
|
||||
targetFrame.setPixel(strokePoints[i].col, strokePoints[i].row, color);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
@ -4,46 +4,46 @@
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.SimplePen = function() {
|
||||
this.toolId = "tool-pen";
|
||||
this.helpText = "Pen tool";
|
||||
ns.SimplePen = function() {
|
||||
this.toolId = "tool-pen";
|
||||
this.helpText = "Pen tool";
|
||||
|
||||
this.previousCol = null;
|
||||
this.previousRow = null;
|
||||
this.previousCol = null;
|
||||
this.previousRow = null;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.SimplePen, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.SimplePen.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
if (frame.containsPixel(col, row)) {
|
||||
frame.setPixel(col, row, color);
|
||||
}
|
||||
this.previousCol = col;
|
||||
this.previousRow = row;
|
||||
};
|
||||
pskl.utils.inherit(ns.SimplePen, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.SimplePen.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
if (frame.containsPixel(col, row)) {
|
||||
frame.setPixel(col, row, color);
|
||||
}
|
||||
this.previousCol = col;
|
||||
this.previousRow = row;
|
||||
};
|
||||
|
||||
ns.SimplePen.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
if((Math.abs(col - this.previousCol) > 1) || (Math.abs(row - this.previousRow) > 1)) {
|
||||
// The pen movement is too fast for the mousemove frequency, there is a gap between the
|
||||
// current point and the previously drawn one.
|
||||
// We fill the gap by calculating missing dots (simple linear interpolation) and draw them.
|
||||
var interpolatedPixels = this.getLinePixels_(col, this.previousCol, row, this.previousRow);
|
||||
for(var i=0, l=interpolatedPixels.length; i<l; i++) {
|
||||
var coords = interpolatedPixels[i];
|
||||
this.applyToolAt(coords.col, coords.row, color, frame, overlay);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.applyToolAt(col, row, color, frame, overlay);
|
||||
}
|
||||
ns.SimplePen.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
if((Math.abs(col - this.previousCol) > 1) || (Math.abs(row - this.previousRow) > 1)) {
|
||||
// The pen movement is too fast for the mousemove frequency, there is a gap between the
|
||||
// current point and the previously drawn one.
|
||||
// We fill the gap by calculating missing dots (simple linear interpolation) and draw them.
|
||||
var interpolatedPixels = this.getLinePixels_(col, this.previousCol, row, this.previousRow);
|
||||
for(var i=0, l=interpolatedPixels.length; i<l; i++) {
|
||||
var coords = interpolatedPixels[i];
|
||||
this.applyToolAt(coords.col, coords.row, color, frame, overlay);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.applyToolAt(col, row, color, frame, overlay);
|
||||
}
|
||||
|
||||
this.previousCol = col;
|
||||
this.previousRow = row;
|
||||
};
|
||||
this.previousCol = col;
|
||||
this.previousRow = row;
|
||||
};
|
||||
})();
|
||||
|
@ -4,77 +4,77 @@
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.Stroke = function() {
|
||||
this.toolId = "tool-stroke";
|
||||
this.helpText = "Stroke tool";
|
||||
ns.Stroke = function() {
|
||||
this.toolId = "tool-stroke";
|
||||
this.helpText = "Stroke tool";
|
||||
|
||||
// Stroke's first point coordinates (set in applyToolAt)
|
||||
this.startCol = null;
|
||||
this.startRow = null;
|
||||
};
|
||||
// Stroke's first point coordinates (set in applyToolAt)
|
||||
this.startCol = null;
|
||||
this.startRow = null;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.Stroke, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Stroke.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.startCol = col;
|
||||
this.startRow = row;
|
||||
|
||||
// When drawing a stroke we don't change the model instantly, since the
|
||||
// user can move his cursor to change the stroke direction and length
|
||||
// dynamically. Instead we draw the (preview) stroke in a fake canvas that
|
||||
// overlay the drawing canvas.
|
||||
// We wait for the releaseToolAt callback to impact both the
|
||||
// frame model and canvas rendering.
|
||||
pskl.utils.inherit(ns.Stroke, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Stroke.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.startCol = col;
|
||||
this.startRow = row;
|
||||
|
||||
// When drawing a stroke we don't change the model instantly, since the
|
||||
// user can move his cursor to change the stroke direction and length
|
||||
// dynamically. Instead we draw the (preview) stroke in a fake canvas that
|
||||
// overlay the drawing canvas.
|
||||
// We wait for the releaseToolAt callback to impact both the
|
||||
// frame model and canvas rendering.
|
||||
|
||||
// The fake canvas where we will draw the preview of the stroke:
|
||||
// Drawing the first point of the stroke in the fake overlay canvas:
|
||||
overlay.setPixel(col, row, color);
|
||||
};
|
||||
// The fake canvas where we will draw the preview of the stroke:
|
||||
// Drawing the first point of the stroke in the fake overlay canvas:
|
||||
overlay.setPixel(col, row, color);
|
||||
};
|
||||
|
||||
ns.Stroke.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
ns.Stroke.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
|
||||
// When the user moussemove (before releasing), we dynamically compute the
|
||||
// pixel to draw the line and draw this line in the overlay canvas:
|
||||
var strokePoints = this.getLinePixels_(this.startCol, col, this.startRow, row);
|
||||
|
||||
// Drawing current stroke:
|
||||
for(var i = 0; i< strokePoints.length; i++) {
|
||||
// When the user moussemove (before releasing), we dynamically compute the
|
||||
// pixel to draw the line and draw this line in the overlay canvas:
|
||||
var strokePoints = this.getLinePixels_(this.startCol, col, this.startRow, row);
|
||||
|
||||
// Drawing current stroke:
|
||||
for(var i = 0; i< strokePoints.length; i++) {
|
||||
|
||||
if(color == Constants.TRANSPARENT_COLOR) {
|
||||
// When mousemoving the stroke tool, we draw in the canvas overlay above the drawing canvas.
|
||||
// If the stroke color is transparent, we won't be
|
||||
// able to see it during the movement.
|
||||
// We set it to a semi-opaque white during the tool mousemove allowing to see colors below the stroke.
|
||||
// When the stroke tool will be released, It will draw a transparent stroke,
|
||||
// eg deleting the equivalent of a stroke.
|
||||
color = Constants.SELECTION_TRANSPARENT_COLOR;
|
||||
}
|
||||
overlay.setPixel(strokePoints[i].col, strokePoints[i].row, color);
|
||||
}
|
||||
};
|
||||
if(color == Constants.TRANSPARENT_COLOR) {
|
||||
// When mousemoving the stroke tool, we draw in the canvas overlay above the drawing canvas.
|
||||
// If the stroke color is transparent, we won't be
|
||||
// able to see it during the movement.
|
||||
// We set it to a semi-opaque white during the tool mousemove allowing to see colors below the stroke.
|
||||
// When the stroke tool will be released, It will draw a transparent stroke,
|
||||
// eg deleting the equivalent of a stroke.
|
||||
color = Constants.SELECTION_TRANSPARENT_COLOR;
|
||||
}
|
||||
overlay.setPixel(strokePoints[i].col, strokePoints[i].row, color);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Stroke.prototype.releaseToolAt = function(col, row, color, frame, overlay) {
|
||||
// If the stroke tool is released outside of the canvas, we cancel the stroke:
|
||||
// TODO: Mutualize this check in common method
|
||||
if(frame.containsPixel(col, row)) {
|
||||
// The user released the tool to draw a line. We will compute the pixel coordinate, impact
|
||||
// the model and draw them in the drawing canvas (not the fake overlay anymore)
|
||||
var strokePoints = this.getLinePixels_(this.startCol, col, this.startRow, row);
|
||||
for(var i = 0; i< strokePoints.length; i++) {
|
||||
// Change model:
|
||||
frame.setPixel(strokePoints[i].col, strokePoints[i].row, color);
|
||||
}
|
||||
}
|
||||
// For now, we are done with the stroke tool and don't need an overlay anymore:
|
||||
overlay.clear();
|
||||
};
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Stroke.prototype.releaseToolAt = function(col, row, color, frame, overlay) {
|
||||
// If the stroke tool is released outside of the canvas, we cancel the stroke:
|
||||
// TODO: Mutualize this check in common method
|
||||
if(frame.containsPixel(col, row)) {
|
||||
// The user released the tool to draw a line. We will compute the pixel coordinate, impact
|
||||
// the model and draw them in the drawing canvas (not the fake overlay anymore)
|
||||
var strokePoints = this.getLinePixels_(this.startCol, col, this.startRow, row);
|
||||
for(var i = 0; i< strokePoints.length; i++) {
|
||||
// Change model:
|
||||
frame.setPixel(strokePoints[i].col, strokePoints[i].row, color);
|
||||
}
|
||||
}
|
||||
// For now, we are done with the stroke tool and don't need an overlay anymore:
|
||||
overlay.clear();
|
||||
};
|
||||
})();
|
||||
|
@ -1,46 +1,46 @@
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.VerticalMirrorPen = function() {
|
||||
this.toolId = "tool-vertical-mirror-pen";
|
||||
this.helpText = "vertical mirror pen tool";
|
||||
ns.VerticalMirrorPen = function() {
|
||||
this.toolId = "tool-vertical-mirror-pen";
|
||||
this.helpText = "vertical mirror pen tool";
|
||||
|
||||
this.swap = null;
|
||||
this.mirroredPreviousCol = null;
|
||||
this.mirroredPreviousRow = null;
|
||||
};
|
||||
this.swap = null;
|
||||
this.mirroredPreviousCol = null;
|
||||
this.mirroredPreviousRow = null;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.VerticalMirrorPen, ns.SimplePen);
|
||||
|
||||
pskl.utils.inherit(ns.VerticalMirrorPen, ns.SimplePen);
|
||||
|
||||
|
||||
ns.VerticalMirrorPen.prototype.setMirrorContext = function() {
|
||||
this.swap = this.previousCol;
|
||||
this.previousCol = this.mirroredPreviousCol;
|
||||
};
|
||||
ns.VerticalMirrorPen.prototype.setMirrorContext = function() {
|
||||
this.swap = this.previousCol;
|
||||
this.previousCol = this.mirroredPreviousCol;
|
||||
};
|
||||
|
||||
ns.VerticalMirrorPen.prototype.unsetMirrorContext = function() {
|
||||
this.mirroredPreviousCol = this.previousCol;
|
||||
this.previousCol = this.swap;
|
||||
};
|
||||
ns.VerticalMirrorPen.prototype.unsetMirrorContext = function() {
|
||||
this.mirroredPreviousCol = this.previousCol;
|
||||
this.previousCol = this.swap;
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.VerticalMirrorPen.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.superclass.applyToolAt.call(this, col, row, color, frame, overlay);
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.VerticalMirrorPen.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.superclass.applyToolAt.call(this, col, row, color, frame, overlay);
|
||||
|
||||
var mirroredCol = this.getSymmetricCol_(col, frame);
|
||||
this.mirroredPreviousCol = mirroredCol;
|
||||
var mirroredCol = this.getSymmetricCol_(col, frame);
|
||||
this.mirroredPreviousCol = mirroredCol;
|
||||
|
||||
this.setMirrorContext();
|
||||
this.superclass.applyToolAt.call(this, mirroredCol, row, color, frame, overlay);
|
||||
this.unsetMirrorContext();
|
||||
};
|
||||
this.setMirrorContext();
|
||||
this.superclass.applyToolAt.call(this, mirroredCol, row, color, frame, overlay);
|
||||
this.unsetMirrorContext();
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.VerticalMirrorPen.prototype.getSymmetricCol_ = function(col, frame) {
|
||||
return frame.getWidth() - col - 1;
|
||||
};
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.VerticalMirrorPen.prototype.getSymmetricCol_ = function(col, frame) {
|
||||
return frame.getWidth() - col - 1;
|
||||
};
|
||||
})();
|
||||
|
@ -4,147 +4,157 @@
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.BaseSelect = function() {
|
||||
this.secondaryToolId = "tool-move";
|
||||
this.BodyRoot = $('body');
|
||||
|
||||
// Select's first point coordinates (set in applyToolAt)
|
||||
this.startCol = null;
|
||||
this.startRow = null;
|
||||
};
|
||||
ns.BaseSelect = function() {
|
||||
this.secondaryToolId = "tool-move";
|
||||
this.BodyRoot = $('body');
|
||||
|
||||
// Select's first point coordinates (set in applyToolAt)
|
||||
this.startCol = null;
|
||||
this.startRow = null;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.BaseSelect, ns.BaseTool);
|
||||
pskl.utils.inherit(ns.BaseSelect, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.BaseSelect.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.startCol = col;
|
||||
this.startRow = row;
|
||||
|
||||
this.lastCol = col;
|
||||
this.lastRow = row;
|
||||
|
||||
// The select tool can be in two different state.
|
||||
// If the inital click of the tool is not on a selection, we go in "select"
|
||||
// mode to create a selection.
|
||||
// If the initial click is on a previous selection, we go in "moveSelection"
|
||||
// mode to allow to move the selection by drag'n dropping it.
|
||||
if(overlay.getPixel(col, row) != Constants.SELECTION_TRANSPARENT_COLOR) {
|
||||
|
||||
this.mode = "select";
|
||||
this.onSelectStart_(col, row, color, frame, overlay);
|
||||
}
|
||||
else {
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.BaseSelect.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.startCol = col;
|
||||
this.startRow = row;
|
||||
|
||||
this.lastCol = col;
|
||||
this.lastRow = row;
|
||||
|
||||
// The select tool can be in two different state.
|
||||
// If the inital click of the tool is not on a selection, we go in "select"
|
||||
// mode to create a selection.
|
||||
// If the initial click is on a previous selection, we go in "moveSelection"
|
||||
// mode to allow to move the selection by drag'n dropping it.
|
||||
if(overlay.getPixel(col, row) != Constants.SELECTION_TRANSPARENT_COLOR) {
|
||||
|
||||
this.mode = "select";
|
||||
this.onSelectStart_(col, row, color, frame, overlay);
|
||||
}
|
||||
else {
|
||||
|
||||
this.mode = "moveSelection";
|
||||
this.onSelectionDragStart_(col, row, color, frame, overlay);
|
||||
}
|
||||
};
|
||||
this.mode = "moveSelection";
|
||||
this.onSelectionDragStart_(col, row, color, frame, overlay);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.BaseSelect.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
if(this.mode == "select") {
|
||||
|
||||
this.onSelect_(col, row, color, frame, overlay);
|
||||
}
|
||||
else if(this.mode == "moveSelection") {
|
||||
|
||||
this.onSelectionDrag_(col, row, color, frame, overlay);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.BaseSelect.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
if(this.mode == "select") {
|
||||
|
||||
this.onSelect_(col, row, color, frame, overlay);
|
||||
}
|
||||
else if(this.mode == "moveSelection") {
|
||||
|
||||
this.onSelectionDrag_(col, row, color, frame, overlay);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.BaseSelect.prototype.releaseToolAt = function(col, row, color, frame, overlay) {
|
||||
if(this.mode == "select") {
|
||||
|
||||
this.onSelectEnd_(col, row, color, frame, overlay);
|
||||
} else if(this.mode == "moveSelection") {
|
||||
|
||||
this.onSelectionDragEnd_(col, row, color, frame, overlay);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.BaseSelect.prototype.releaseToolAt = function(col, row, color, frame, overlay) {
|
||||
if(this.mode == "select") {
|
||||
this.onSelectEnd_(col, row, color, frame, overlay);
|
||||
} else if(this.mode == "moveSelection") {
|
||||
|
||||
this.onSelectionDragEnd_(col, row, color, frame, overlay);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* If we mouseover the selection draw inside the overlay frame, show the 'move' cursor
|
||||
* instead of the 'select' one. It indicates that we can move the selection by dragndroping it.
|
||||
* @override
|
||||
*/
|
||||
ns.BaseSelect.prototype.moveUnactiveToolAt = function(col, row, color, frame, overlay) {
|
||||
|
||||
if(overlay.getPixel(col, row) != Constants.SELECTION_TRANSPARENT_COLOR) {
|
||||
// We're hovering the selection, show the move tool:
|
||||
this.BodyRoot.addClass(this.toolId);
|
||||
this.BodyRoot.removeClass(this.secondaryToolId);
|
||||
} else {
|
||||
// We're not hovering the selection, show create selection tool:
|
||||
this.BodyRoot.addClass(this.secondaryToolId);
|
||||
this.BodyRoot.removeClass(this.toolId);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* If we mouseover the selection draw inside the overlay frame, show the 'move' cursor
|
||||
* instead of the 'select' one. It indicates that we can move the selection by dragndroping it.
|
||||
* @override
|
||||
*/
|
||||
ns.BaseSelect.prototype.moveUnactiveToolAt = function(col, row, color, frame, overlay) {
|
||||
|
||||
if(overlay.getPixel(col, row) != Constants.SELECTION_TRANSPARENT_COLOR) {
|
||||
// We're hovering the selection, show the move tool:
|
||||
this.BodyRoot.addClass(this.toolId);
|
||||
this.BodyRoot.removeClass(this.secondaryToolId);
|
||||
} else {
|
||||
// We're not hovering the selection, show create selection tool:
|
||||
this.BodyRoot.addClass(this.secondaryToolId);
|
||||
this.BodyRoot.removeClass(this.toolId);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Move the overlay frame filled with semi-transparent pixels that represent the selection.
|
||||
* @private
|
||||
*/
|
||||
ns.BaseSelect.prototype.shiftOverlayFrame_ = function (colDiff, rowDiff, overlayFrame, reference) {
|
||||
var color;
|
||||
for (var col = 0 ; col < overlayFrame.getWidth() ; col++) {
|
||||
for (var row = 0 ; row < overlayFrame.getHeight() ; row++) {
|
||||
if (reference.containsPixel(col - colDiff, row - rowDiff)) {
|
||||
color = reference.getPixel(col - colDiff, row - rowDiff);
|
||||
} else {
|
||||
color = Constants.TRANSPARENT_COLOR;
|
||||
}
|
||||
overlayFrame.setPixel(col, row, color);
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* For each pixel in the selection draw it in white transparent on the tool overlay
|
||||
* @protected
|
||||
*/
|
||||
ns.BaseSelect.prototype.drawSelectionOnOverlay_ = function (selection, overlay) {
|
||||
var pixels = selection.pixels;
|
||||
for(var i=0, l=pixels.length; i<l; i++) {
|
||||
overlay.setPixel(pixels[i].col, pixels[i].row, Constants.SELECTION_TRANSPARENT_COLOR);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Move the overlay frame filled with semi-transparent pixels that represent the selection.
|
||||
* @private
|
||||
*/
|
||||
ns.BaseSelect.prototype.shiftOverlayFrame_ = function (colDiff, rowDiff, overlayFrame, reference) {
|
||||
var color;
|
||||
for (var col = 0 ; col < overlayFrame.getWidth() ; col++) {
|
||||
for (var row = 0 ; row < overlayFrame.getHeight() ; row++) {
|
||||
if (reference.containsPixel(col - colDiff, row - rowDiff)) {
|
||||
color = reference.getPixel(col - colDiff, row - rowDiff);
|
||||
} else {
|
||||
color = Constants.TRANSPARENT_COLOR;
|
||||
}
|
||||
overlayFrame.setPixel(col, row, color);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// The list of callbacks to implement by specialized tools to implement the selection creation behavior.
|
||||
/** @protected */
|
||||
ns.BaseSelect.prototype.onSelectStart_ = function (col, row, color, frame, overlay) {};
|
||||
/** @protected */
|
||||
ns.BaseSelect.prototype.onSelect_ = function (col, row, color, frame, overlay) {};
|
||||
/** @protected */
|
||||
ns.BaseSelect.prototype.onSelectEnd_ = function (col, row, color, frame, overlay) {};
|
||||
// The list of callbacks to implement by specialized tools to implement the selection creation behavior.
|
||||
/** @protected */
|
||||
ns.BaseSelect.prototype.onSelectStart_ = function (col, row, color, frame, overlay) {};
|
||||
/** @protected */
|
||||
ns.BaseSelect.prototype.onSelect_ = function (col, row, color, frame, overlay) {};
|
||||
/** @protected */
|
||||
ns.BaseSelect.prototype.onSelectEnd_ = function (col, row, color, frame, overlay) {};
|
||||
|
||||
|
||||
// The list of callbacks that define the drag'n drop behavior of the selection.
|
||||
/** @private */
|
||||
ns.BaseSelect.prototype.onSelectionDragStart_ = function (col, row, color, frame, overlay) {
|
||||
// Since we will move the overlayFrame in which the current selection is rendered,
|
||||
// we clone it to have a reference for the later shifting process.
|
||||
this.overlayFrameReference = overlay.clone();
|
||||
};
|
||||
/** @private */
|
||||
ns.BaseSelect.prototype.onSelectionDrag_ = function (col, row, color, frame, overlay) {
|
||||
var deltaCol = col - this.lastCol;
|
||||
var deltaRow = row - this.lastRow;
|
||||
|
||||
var colDiff = col - this.startCol, rowDiff = row - this.startRow;
|
||||
|
||||
// Shifting selection on overlay frame:
|
||||
this.shiftOverlayFrame_(colDiff, rowDiff, overlay, this.overlayFrameReference);
|
||||
// The list of callbacks that define the drag'n drop behavior of the selection.
|
||||
/** @private */
|
||||
ns.BaseSelect.prototype.onSelectionDragStart_ = function (col, row, color, frame, overlay) {
|
||||
// Since we will move the overlayFrame in which the current selection is rendered,
|
||||
// we clone it to have a reference for the later shifting process.
|
||||
this.overlayFrameReference = overlay.clone();
|
||||
};
|
||||
|
||||
/** @private */
|
||||
ns.BaseSelect.prototype.onSelectionDrag_ = function (col, row, color, frame, overlay) {
|
||||
var deltaCol = col - this.lastCol;
|
||||
var deltaRow = row - this.lastRow;
|
||||
|
||||
var colDiff = col - this.startCol, rowDiff = row - this.startRow;
|
||||
|
||||
// Shifting selection on overlay frame:
|
||||
this.shiftOverlayFrame_(colDiff, rowDiff, overlay, this.overlayFrameReference);
|
||||
|
||||
// Update selection model:
|
||||
$.publish(Events.SELECTION_MOVE_REQUEST, [deltaCol, deltaRow]);
|
||||
|
||||
this.lastCol = col;
|
||||
this.lastRow = row;
|
||||
};
|
||||
/** @private */
|
||||
ns.BaseSelect.prototype.onSelectionDragEnd_ = function (col, row, color, frame, overlay) {
|
||||
this.onSelectionDrag_(col, row, color, frame, overlay);
|
||||
};
|
||||
// Update selection model:
|
||||
$.publish(Events.SELECTION_MOVE_REQUEST, [deltaCol, deltaRow]);
|
||||
|
||||
this.lastCol = col;
|
||||
this.lastRow = row;
|
||||
};
|
||||
|
||||
/** @private */
|
||||
ns.BaseSelect.prototype.onSelectionDragEnd_ = function (col, row, color, frame, overlay) {
|
||||
this.onSelectionDrag_(col, row, color, frame, overlay);
|
||||
};
|
||||
})();
|
||||
|
@ -4,48 +4,49 @@
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.RectangleSelect = function() {
|
||||
this.toolId = "tool-rectangle-select";
|
||||
this.helpText = "Rectangle selection tool";
|
||||
|
||||
ns.BaseSelect.call(this);
|
||||
};
|
||||
ns.RectangleSelect = function() {
|
||||
this.toolId = "tool-rectangle-select";
|
||||
this.helpText = "Rectangle selection tool";
|
||||
|
||||
ns.BaseSelect.call(this);
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.RectangleSelect, ns.BaseSelect);
|
||||
|
||||
pskl.utils.inherit(ns.RectangleSelect, ns.BaseSelect);
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.RectangleSelect.prototype.onSelectStart_ = function (col, row, color, frame, overlay) {
|
||||
// Drawing the first point of the rectangle in the fake overlay canvas:
|
||||
overlay.setPixel(col, row, color);
|
||||
};
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.RectangleSelect.prototype.onSelectStart_ = function (col, row, color, frame, overlay) {
|
||||
// Drawing the first point of the rectangle in the fake overlay canvas:
|
||||
overlay.setPixel(col, row, color);
|
||||
};
|
||||
|
||||
/**
|
||||
* When creating the rectangle selection, we clear the current overlayFrame and
|
||||
* redraw the current rectangle based on the orgin coordinate and
|
||||
* the current mouse coordiinate in sprite.
|
||||
* @override
|
||||
*/
|
||||
ns.RectangleSelect.prototype.onSelect_ = function (col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
if(this.startCol == col &&this.startRow == row) {
|
||||
$.publish(Events.SELECTION_DISMISSED);
|
||||
} else {
|
||||
var selection = new pskl.selection.RectangularSelection(
|
||||
this.startCol, this.startRow, col, row);
|
||||
$.publish(Events.SELECTION_CREATED, [selection]);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* When creating the rectangle selection, we clear the current overlayFrame and
|
||||
* redraw the current rectangle based on the orgin coordinate and
|
||||
* the current mouse coordiinate in sprite.
|
||||
* @override
|
||||
*/
|
||||
ns.RectangleSelect.prototype.onSelect_ = function (col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
if(this.startCol == col &&this.startRow == row) {
|
||||
$.publish(Events.SELECTION_DISMISSED);
|
||||
} else {
|
||||
var selection = new pskl.selection.RectangularSelection(
|
||||
this.startCol, this.startRow, col, row);
|
||||
$.publish(Events.SELECTION_CREATED, [selection]);
|
||||
this.drawSelectionOnOverlay_(selection, overlay);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.RectangleSelect.prototype.onSelectEnd_ = function (col, row, color, frame, overlay) {
|
||||
this.onSelect_(col, row, color, frame, overlay);
|
||||
};
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.RectangleSelect.prototype.onSelectEnd_ = function (col, row, color, frame, overlay) {
|
||||
this.onSelect_(col, row, color, frame, overlay);
|
||||
};
|
||||
|
||||
})();
|
||||
|
@ -4,31 +4,33 @@
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.ShapeSelect = function() {
|
||||
this.toolId = "tool-shape-select";
|
||||
this.helpText = "Shape selection tool";
|
||||
|
||||
ns.BaseSelect.call(this);
|
||||
};
|
||||
ns.ShapeSelect = function() {
|
||||
this.toolId = "tool-shape-select";
|
||||
this.helpText = "Shape selection tool";
|
||||
|
||||
ns.BaseSelect.call(this);
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.ShapeSelect, ns.BaseSelect);
|
||||
|
||||
pskl.utils.inherit(ns.ShapeSelect, ns.BaseSelect);
|
||||
|
||||
/**
|
||||
* For the shape select tool, you just need to click one time to create a selection.
|
||||
* So we jsut need to implement onSelectStart_ (no need for onSelect_ & onSelectEnd_)
|
||||
* @override
|
||||
*/
|
||||
ns.ShapeSelect.prototype.onSelectStart_ = function (col, row, color, frame, overlay) {
|
||||
// Clean previous selection:
|
||||
$.publish(Events.SELECTION_DISMISSED);
|
||||
overlay.clear();
|
||||
|
||||
// From the pixel cliked, get shape using an algorithm similar to the paintbucket one:
|
||||
var pixels = pskl.PixelUtils.getSimilarConnectedPixelsFromFrame(frame, col, row);
|
||||
var selection = new pskl.selection.ShapeSelection(pixels);
|
||||
|
||||
/**
|
||||
* For the shape select tool, you just need to click one time to create a selection.
|
||||
* So we jsut need to implement onSelectStart_ (no need for onSelect_ & onSelectEnd_)
|
||||
* @override
|
||||
*/
|
||||
ns.ShapeSelect.prototype.onSelectStart_ = function (col, row, color, frame, overlay) {
|
||||
// Clean previous selection:
|
||||
$.publish(Events.SELECTION_DISMISSED);
|
||||
|
||||
// From the pixel cliked, get shape using an algorithm similar to the paintbucket one:
|
||||
var pixels = pskl.PixelUtils.getSimilarConnectedPixelsFromFrame(frame, col, row);
|
||||
var selection = new pskl.selection.ShapeSelection(pixels);
|
||||
$.publish(Events.SELECTION_CREATED, [selection]);
|
||||
};
|
||||
$.publish(Events.SELECTION_CREATED, [selection]);
|
||||
this.drawSelectionOnOverlay_(selection, overlay);
|
||||
};
|
||||
|
||||
})();
|
||||
|
@ -16,7 +16,7 @@
|
||||
//import flash.net.URLRequest;
|
||||
//import flash.net.navigateToURL;
|
||||
|
||||
GIFEncoder = function()
|
||||
window.GIFEncoder = function()
|
||||
{
|
||||
for(var i = 0, chr = {}; i < 256; i++)
|
||||
chr[i] = String.fromCharCode(i);
|
||||
|
@ -1,4 +1,4 @@
|
||||
function encode64(input) {
|
||||
window.encode64 = function(input) {
|
||||
var output = "", i = 0, l = input.length,
|
||||
key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
|
||||
chr1, chr2, chr3, enc1, enc2, enc3, enc4;
|
||||
@ -15,4 +15,4 @@ function encode64(input) {
|
||||
output = output + key.charAt(enc1) + key.charAt(enc2) + key.charAt(enc3) + key.charAt(enc4);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
@ -1,118 +1,118 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.model");
|
||||
|
||||
ns.Frame = function (pixels) {
|
||||
this.pixels = pixels;
|
||||
this.previousStates = [this.getPixels()];
|
||||
this.stateIndex = 0;
|
||||
};
|
||||
var ns = $.namespace("pskl.model");
|
||||
|
||||
ns.Frame = function (pixels) {
|
||||
this.pixels = pixels;
|
||||
this.previousStates = [this.getPixels()];
|
||||
this.stateIndex = 0;
|
||||
};
|
||||
|
||||
ns.Frame.createEmpty = function (width, height) {
|
||||
var pixels = ns.Frame.createEmptyPixelGrid_(width, height);
|
||||
return new ns.Frame(pixels);
|
||||
};
|
||||
ns.Frame.createEmpty = function (width, height) {
|
||||
var pixels = ns.Frame.createEmptyPixelGrid_(width, height);
|
||||
return new ns.Frame(pixels);
|
||||
};
|
||||
|
||||
ns.Frame.createEmptyPixelGrid_ = function (width, height) {
|
||||
var pixels = []; //new Array(width);
|
||||
for (var columnIndex=0; columnIndex < width; columnIndex++) {
|
||||
var columnArray = [];
|
||||
for(var heightIndex = 0; heightIndex < height; heightIndex++) {
|
||||
columnArray.push(Constants.TRANSPARENT_COLOR);
|
||||
}
|
||||
pixels[columnIndex] = columnArray;
|
||||
}
|
||||
return pixels;
|
||||
};
|
||||
ns.Frame.createEmptyPixelGrid_ = function (width, height) {
|
||||
var pixels = []; //new Array(width);
|
||||
for (var columnIndex=0; columnIndex < width; columnIndex++) {
|
||||
var columnArray = [];
|
||||
for(var heightIndex = 0; heightIndex < height; heightIndex++) {
|
||||
columnArray.push(Constants.TRANSPARENT_COLOR);
|
||||
}
|
||||
pixels[columnIndex] = columnArray;
|
||||
}
|
||||
return pixels;
|
||||
};
|
||||
|
||||
ns.Frame.createEmptyFromFrame = function (frame) {
|
||||
return ns.Frame.createEmpty(frame.getWidth(), frame.getHeight());
|
||||
};
|
||||
ns.Frame.createEmptyFromFrame = function (frame) {
|
||||
return ns.Frame.createEmpty(frame.getWidth(), frame.getHeight());
|
||||
};
|
||||
|
||||
ns.Frame.prototype.clone = function () {
|
||||
return new ns.Frame(this.getPixels());
|
||||
};
|
||||
ns.Frame.prototype.clone = function () {
|
||||
return new ns.Frame(this.getPixels());
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a copy of the pixels used by the frame
|
||||
*/
|
||||
ns.Frame.prototype.getPixels = function () {
|
||||
return this.clonePixels_(this.pixels);
|
||||
};
|
||||
/**
|
||||
* Returns a copy of the pixels used by the frame
|
||||
*/
|
||||
ns.Frame.prototype.getPixels = function () {
|
||||
return this.clonePixels_(this.pixels);
|
||||
};
|
||||
|
||||
/**
|
||||
* Copies the passed pixels into the frame.
|
||||
*/
|
||||
ns.Frame.prototype.setPixels = function (pixels) {
|
||||
this.pixels = this.clonePixels_(pixels);
|
||||
};
|
||||
/**
|
||||
* Copies the passed pixels into the frame.
|
||||
*/
|
||||
ns.Frame.prototype.setPixels = function (pixels) {
|
||||
this.pixels = this.clonePixels_(pixels);
|
||||
};
|
||||
|
||||
|
||||
|
||||
ns.Frame.prototype.clear = function () {
|
||||
var pixels = ns.Frame.createEmptyPixelGrid_(this.getWidth(), this.getHeight());
|
||||
this.setPixels(pixels);
|
||||
};
|
||||
ns.Frame.prototype.clear = function () {
|
||||
var pixels = ns.Frame.createEmptyPixelGrid_(this.getWidth(), this.getHeight());
|
||||
this.setPixels(pixels);
|
||||
};
|
||||
|
||||
/**
|
||||
* Clone a set of pixels. Should be static utility method
|
||||
* @private
|
||||
*/
|
||||
ns.Frame.prototype.clonePixels_ = function (pixels) {
|
||||
var clonedPixels = [];
|
||||
for (var col = 0 ; col < pixels.length ; col++) {
|
||||
clonedPixels[col] = pixels[col].slice(0 , pixels[col].length);
|
||||
}
|
||||
return clonedPixels;
|
||||
};
|
||||
/**
|
||||
* Clone a set of pixels. Should be static utility method
|
||||
* @private
|
||||
*/
|
||||
ns.Frame.prototype.clonePixels_ = function (pixels) {
|
||||
var clonedPixels = [];
|
||||
for (var col = 0 ; col < pixels.length ; col++) {
|
||||
clonedPixels[col] = pixels[col].slice(0 , pixels[col].length);
|
||||
}
|
||||
return clonedPixels;
|
||||
};
|
||||
|
||||
ns.Frame.prototype.serialize = function () {
|
||||
return JSON.stringify(this.pixels);
|
||||
};
|
||||
ns.Frame.prototype.serialize = function () {
|
||||
return JSON.stringify(this.pixels);
|
||||
};
|
||||
|
||||
ns.Frame.prototype.setPixel = function (col, row, color) {
|
||||
this.pixels[col][row] = color;
|
||||
};
|
||||
ns.Frame.prototype.setPixel = function (col, row, color) {
|
||||
this.pixels[col][row] = color;
|
||||
};
|
||||
|
||||
ns.Frame.prototype.getPixel = function (col, row) {
|
||||
return this.pixels[col][row];
|
||||
};
|
||||
ns.Frame.prototype.getPixel = function (col, row) {
|
||||
return this.pixels[col][row];
|
||||
};
|
||||
|
||||
ns.Frame.prototype.getWidth = function () {
|
||||
return this.pixels.length;
|
||||
};
|
||||
ns.Frame.prototype.getWidth = function () {
|
||||
return this.pixels.length;
|
||||
};
|
||||
|
||||
ns.Frame.prototype.getHeight = function () {
|
||||
return this.pixels[0].length;
|
||||
};
|
||||
ns.Frame.prototype.getHeight = function () {
|
||||
return this.pixels[0].length;
|
||||
};
|
||||
|
||||
ns.Frame.prototype.containsPixel = function (col, row) {
|
||||
return col >= 0 && row >= 0 && col < this.pixels.length && row < this.pixels[0].length;
|
||||
};
|
||||
ns.Frame.prototype.containsPixel = function (col, row) {
|
||||
return col >= 0 && row >= 0 && col < this.pixels.length && row < this.pixels[0].length;
|
||||
};
|
||||
|
||||
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.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.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.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();
|
||||
};
|
||||
ns.Frame.prototype.isSameSize = function (otherFrame) {
|
||||
return this.getHeight() == otherFrame.getHeight() && this.getWidth() == otherFrame.getWidth();
|
||||
};
|
||||
})();
|
@ -1,157 +1,157 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.model");
|
||||
ns.FrameSheet = function (height, width) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.frames = [];
|
||||
this.currentFrameIndex = 0;
|
||||
};
|
||||
var ns = $.namespace("pskl.model");
|
||||
ns.FrameSheet = function (height, width) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.frames = [];
|
||||
this.currentFrameIndex = 0;
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.getHeight = function () {
|
||||
return this.height;
|
||||
};
|
||||
ns.FrameSheet.prototype.getHeight = function () {
|
||||
return this.height;
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.getWidth = function () {
|
||||
return this.width;
|
||||
};
|
||||
ns.FrameSheet.prototype.getWidth = function () {
|
||||
return this.width;
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.addEmptyFrame = function () {
|
||||
this.addFrame(ns.Frame.createEmpty(this.width, this.height));
|
||||
};
|
||||
ns.FrameSheet.prototype.addEmptyFrame = function () {
|
||||
this.addFrame(ns.Frame.createEmpty(this.width, this.height));
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.addFrame = function (frame) {
|
||||
this.frames.push(frame);
|
||||
};
|
||||
ns.FrameSheet.prototype.addFrame = function (frame) {
|
||||
this.frames.push(frame);
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.getFrameCount = function () {
|
||||
return this.frames.length;
|
||||
};
|
||||
ns.FrameSheet.prototype.getFrameCount = function () {
|
||||
return this.frames.length;
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.getCurrentFrame = function () {
|
||||
return this.frames[this.currentFrameIndex];
|
||||
};
|
||||
ns.FrameSheet.prototype.getCurrentFrame = function () {
|
||||
return this.frames[this.currentFrameIndex];
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.setCurrentFrameIndex = function (index) {
|
||||
this.currentFrameIndex = index;
|
||||
$.publish(Events.CURRENT_FRAME_SET, [this.getCurrentFrame()]);
|
||||
$.publish(Events.FRAMESHEET_RESET); // Is it no to overkill to have this here ?
|
||||
};
|
||||
ns.FrameSheet.prototype.setCurrentFrameIndex = function (index) {
|
||||
this.currentFrameIndex = index;
|
||||
$.publish(Events.CURRENT_FRAME_SET, [this.getCurrentFrame()]);
|
||||
$.publish(Events.FRAMESHEET_RESET); // Is it no to overkill to have this here ?
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.getUsedColors = function() {
|
||||
var colors = {};
|
||||
for (var frameIndex=0; frameIndex < this.frames.length; frameIndex++) {
|
||||
var frame = this.frames[frameIndex];
|
||||
for (var i = 0, width = frame.getWidth(); i < width ; i++) {
|
||||
var line = frame[i];
|
||||
for (var j = 0, height = frame.getHeight() ; j < height ; j++) {
|
||||
var pixel = frame.getPixel(i, j);
|
||||
colors[pixel] = pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
return colors;
|
||||
};
|
||||
ns.FrameSheet.prototype.getUsedColors = function() {
|
||||
var colors = {};
|
||||
for (var frameIndex=0; frameIndex < this.frames.length; frameIndex++) {
|
||||
var frame = this.frames[frameIndex];
|
||||
for (var i = 0, width = frame.getWidth(); i < width ; i++) {
|
||||
var line = frame[i];
|
||||
for (var j = 0, height = frame.getHeight() ; j < height ; j++) {
|
||||
var pixel = frame.getPixel(i, j);
|
||||
colors[pixel] = pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
return colors;
|
||||
};
|
||||
|
||||
// Could be used to pass around model using long GET param (good enough for simple models) and
|
||||
// do some temporary locastorage
|
||||
ns.FrameSheet.prototype.serialize = function() {
|
||||
var serializedFrames = [];
|
||||
for (var i = 0 ; i < this.frames.length ; i++) {
|
||||
serializedFrames.push(this.frames[i].serialize());
|
||||
}
|
||||
return '[' + serializedFrames.join(",") + ']';
|
||||
//return JSON.stringify(frames);
|
||||
};
|
||||
// Could be used to pass around model using long GET param (good enough for simple models) and
|
||||
// do some temporary locastorage
|
||||
ns.FrameSheet.prototype.serialize = function() {
|
||||
var serializedFrames = [];
|
||||
for (var i = 0 ; i < this.frames.length ; i++) {
|
||||
serializedFrames.push(this.frames[i].serialize());
|
||||
}
|
||||
return '[' + serializedFrames.join(",") + ']';
|
||||
//return JSON.stringify(frames);
|
||||
};
|
||||
|
||||
/**
|
||||
* Load a framesheet from a model that might have been persisted in db / localstorage
|
||||
* Overrides existing frames.
|
||||
* @param {String} serialized
|
||||
*/
|
||||
ns.FrameSheet.prototype.deserialize = function (serialized) {
|
||||
try {
|
||||
this.load(JSON.parse(serialized));
|
||||
} catch (e) {
|
||||
throw "Could not load serialized framesheet : " + e.message;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Load a framesheet from a model that might have been persisted in db / localstorage
|
||||
* Overrides existing frames.
|
||||
* @param {String} serialized
|
||||
*/
|
||||
ns.FrameSheet.prototype.deserialize = function (serialized) {
|
||||
try {
|
||||
this.load(JSON.parse(serialized));
|
||||
} catch (e) {
|
||||
throw "Could not load serialized framesheet : " + e.message;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Load a framesheet from a model that might have been persisted in db / localstorage
|
||||
* Overrides existing frames.
|
||||
* @param {String} serialized
|
||||
*/
|
||||
ns.FrameSheet.prototype.load = function (framesheet) {
|
||||
this.frames = [];
|
||||
for (var i = 0 ; i < framesheet.length ; i++) {
|
||||
var frameCfg = framesheet[i];
|
||||
this.addFrame(new ns.Frame(frameCfg));
|
||||
}
|
||||
/**
|
||||
* Load a framesheet from a model that might have been persisted in db / localstorage
|
||||
* Overrides existing frames.
|
||||
* @param {String} serialized
|
||||
*/
|
||||
ns.FrameSheet.prototype.load = function (framesheet) {
|
||||
this.frames = [];
|
||||
for (var i = 0 ; i < framesheet.length ; i++) {
|
||||
var frameCfg = framesheet[i];
|
||||
this.addFrame(new ns.Frame(frameCfg));
|
||||
}
|
||||
|
||||
if (this.hasFrameAtIndex(0)) {
|
||||
this.height = this.getFrameByIndex(0).getHeight();
|
||||
this.width = this.getFrameByIndex(0).getWidth();
|
||||
this.setCurrentFrameIndex(0);
|
||||
$.publish(Events.FRAME_SIZE_CHANGED);
|
||||
}
|
||||
if (this.hasFrameAtIndex(0)) {
|
||||
this.height = this.getFrameByIndex(0).getHeight();
|
||||
this.width = this.getFrameByIndex(0).getWidth();
|
||||
this.setCurrentFrameIndex(0);
|
||||
$.publish(Events.FRAME_SIZE_CHANGED);
|
||||
}
|
||||
|
||||
$.publish(Events.FRAMESHEET_RESET);
|
||||
};
|
||||
$.publish(Events.FRAMESHEET_RESET);
|
||||
};
|
||||
|
||||
|
||||
ns.FrameSheet.prototype.hasFrameAtIndex = function(index) {
|
||||
return (index >= 0 && index < this.getFrameCount());
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.hasFrameAtIndex = function(index) {
|
||||
return (index >= 0 && index < this.getFrameCount());
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.getFrameByIndex = function(index) {
|
||||
if (isNaN(index)) {
|
||||
throw "Bad argument value for getFrameByIndex method: <" + index + ">";
|
||||
}
|
||||
ns.FrameSheet.prototype.getFrameByIndex = function(index) {
|
||||
if (isNaN(index)) {
|
||||
throw "Bad argument value for getFrameByIndex method: <" + index + ">";
|
||||
}
|
||||
|
||||
if (!this.hasFrameAtIndex(index)) {
|
||||
throw "Out of bound index for frameSheet object.";
|
||||
}
|
||||
if (!this.hasFrameAtIndex(index)) {
|
||||
throw "Out of bound index for frameSheet object.";
|
||||
}
|
||||
|
||||
return this.frames[index];
|
||||
};
|
||||
return this.frames[index];
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.removeFrameByIndex = function(index) {
|
||||
if(!this.hasFrameAtIndex(index)) {
|
||||
throw "Out of bound index for frameSheet object.";
|
||||
}
|
||||
this.frames.splice(index, 1);
|
||||
ns.FrameSheet.prototype.removeFrameByIndex = function(index) {
|
||||
if(!this.hasFrameAtIndex(index)) {
|
||||
throw "Out of bound index for frameSheet object.";
|
||||
}
|
||||
this.frames.splice(index, 1);
|
||||
|
||||
// Current frame index might not be valid anymore
|
||||
if (!this.hasFrameAtIndex(this.currentFrameIndex)) {
|
||||
// if not select last frame available
|
||||
this.setCurrentFrameIndex(this.getFrameCount() - 1);
|
||||
}
|
||||
// Current frame index might not be valid anymore
|
||||
if (!this.hasFrameAtIndex(this.currentFrameIndex)) {
|
||||
// if not select last frame available
|
||||
this.setCurrentFrameIndex(this.getFrameCount() - 1);
|
||||
}
|
||||
|
||||
$.publish(Events.FRAMESHEET_RESET);
|
||||
};
|
||||
$.publish(Events.FRAMESHEET_RESET);
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.duplicateFrameByIndex = function(index) {
|
||||
var frame = this.getFrameByIndex(index);
|
||||
this.frames.splice(index + 1, 0, frame.clone());
|
||||
};
|
||||
ns.FrameSheet.prototype.duplicateFrameByIndex = function(index) {
|
||||
var frame = this.getFrameByIndex(index);
|
||||
this.frames.splice(index + 1, 0, frame.clone());
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.moveFrame = function(originIndex, destinationIndex) {
|
||||
this.frames.splice(destinationIndex, 0, this.frames.splice(originIndex, 1)[0]);
|
||||
};
|
||||
ns.FrameSheet.prototype.moveFrame = function(originIndex, destinationIndex) {
|
||||
this.frames.splice(destinationIndex, 0, this.frames.splice(originIndex, 1)[0]);
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.swapFrames = function(indexFrame1, indexFrame2) {
|
||||
if(isNaN(indexFrame1) || isNaN(indexFrame1) ||
|
||||
(!this.hasFrameAtIndex(indexFrame1) && !this.hasFrameAtIndex(indexFrame2))) {
|
||||
throw "Bad indexes for swapFrames Framesheet function.";
|
||||
}
|
||||
if(indexFrame1 == indexFrame2) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
var swapFrame = this.frames[indexFrame1];
|
||||
this.frames[indexFrame1] = this.frames[indexFrame2];
|
||||
this.frames[indexFrame2] = swapFrame;
|
||||
}
|
||||
};
|
||||
ns.FrameSheet.prototype.swapFrames = function(indexFrame1, indexFrame2) {
|
||||
if(isNaN(indexFrame1) || isNaN(indexFrame1) ||
|
||||
(!this.hasFrameAtIndex(indexFrame1) && !this.hasFrameAtIndex(indexFrame2))) {
|
||||
throw "Bad indexes for swapFrames Framesheet function.";
|
||||
}
|
||||
if(indexFrame1 == indexFrame2) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
var swapFrame = this.frames[indexFrame1];
|
||||
this.frames[indexFrame1] = this.frames[indexFrame2];
|
||||
this.frames[indexFrame2] = swapFrame;
|
||||
}
|
||||
};
|
||||
})();
|
74
js/piskel.js
74
js/piskel.js
@ -17,6 +17,7 @@
|
||||
var frameSize = this.readSizeFromURL_();
|
||||
frameSheet = new pskl.model.FrameSheet(frameSize.height, frameSize.width);
|
||||
frameSheet.addEmptyFrame();
|
||||
frameSheet.setCurrentFrameIndex(0);
|
||||
|
||||
/**
|
||||
* True when piskel is running in static mode (no back end needed).
|
||||
@ -25,26 +26,20 @@
|
||||
this.isStaticVersion = !pskl.appEngineToken_;
|
||||
|
||||
this.drawingController = new pskl.controller.DrawingController(frameSheet, $('#drawing-canvas-container'));
|
||||
this.drawingController.init();
|
||||
|
||||
this.animationController = new pskl.controller.AnimatedPreviewController(frameSheet, $('#preview-canvas-container'));
|
||||
this.previewsController = new pskl.controller.PreviewFilmController(frameSheet, $('#preview-list'));
|
||||
this.settingsController = new pskl.controller.SettingsController();
|
||||
|
||||
// To catch the current active frame, the selection manager have to be initialized before
|
||||
// the 'frameSheet.setCurrentFrameIndex(0);' line below.
|
||||
// TODO(vincz): Slice each constructor to have:
|
||||
// - an event(s) listening init
|
||||
// - an event(s) triggering init
|
||||
// All listeners will be hook in a first step, then all event triggering inits will be called
|
||||
// in a second batch.
|
||||
this.selectionManager = new pskl.selection.SelectionManager(frameSheet, this.drawingController.overlayFrame);
|
||||
|
||||
// DO NOT MOVE THIS LINE (see comment above)
|
||||
frameSheet.setCurrentFrameIndex(0);
|
||||
|
||||
this.animationController.init();
|
||||
|
||||
this.previewsController = new pskl.controller.PreviewFilmController(frameSheet, $('#preview-list'));
|
||||
this.previewsController.init();
|
||||
|
||||
this.settingsController = new pskl.controller.SettingsController();
|
||||
this.settingsController.init();
|
||||
|
||||
this.selectionManager = new pskl.selection.SelectionManager(frameSheet);
|
||||
this.selectionManager.init();
|
||||
|
||||
this.historyService = new pskl.service.HistoryService(frameSheet);
|
||||
this.historyService.init();
|
||||
|
||||
@ -57,6 +52,28 @@
|
||||
this.localStorageService = new pskl.service.LocalStorageService(frameSheet);
|
||||
this.localStorageService.init();
|
||||
|
||||
this.toolController = new pskl.controller.ToolController();
|
||||
this.toolController.init();
|
||||
|
||||
this.paletteController = new pskl.controller.PaletteController();
|
||||
this.paletteController.init(frameSheet);
|
||||
|
||||
var drawingLoop = new pskl.rendering.DrawingLoop();
|
||||
drawingLoop.addCallback(this.render, this);
|
||||
drawingLoop.start();
|
||||
|
||||
// Init (event-delegated) bootstrap tooltips:
|
||||
$('body').tooltip({
|
||||
selector: '[rel=tooltip]'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* True when piskel is running in static mode (no back end needed).
|
||||
* When started from APP Engine, appEngineToken_ (Boolean) should be set on window.pskl
|
||||
*/
|
||||
this.isStaticVersion = !pskl.appEngineToken_;
|
||||
|
||||
if (this.isStaticVersion) {
|
||||
var framesheetId = this.readFramesheetIdFromURL_();
|
||||
if (framesheetId) {
|
||||
@ -65,7 +82,6 @@
|
||||
}]);
|
||||
this.loadFramesheetFromService(framesheetId);
|
||||
} else {
|
||||
this.finishInit();
|
||||
this.localStorageService.displayRestoreNotification();
|
||||
}
|
||||
} else {
|
||||
@ -73,17 +89,7 @@
|
||||
frameSheet.load(pskl.framesheetData_.content);
|
||||
pskl.app.animationController.setFPS(pskl.framesheetData_.fps);
|
||||
}
|
||||
this.finishInit();
|
||||
}
|
||||
|
||||
var drawingLoop = new pskl.rendering.DrawingLoop();
|
||||
drawingLoop.addCallback(this.render, this);
|
||||
drawingLoop.start();
|
||||
|
||||
// Init (event-delegated) bootstrap tooltips:
|
||||
$('body').tooltip({
|
||||
selector : '[rel=tooltip]'
|
||||
});
|
||||
},
|
||||
|
||||
render : function (delta) {
|
||||
@ -91,15 +97,7 @@
|
||||
this.animationController.render(delta);
|
||||
this.previewsController.render(delta);
|
||||
},
|
||||
|
||||
finishInit : function () {
|
||||
var toolController = new pskl.controller.ToolController();
|
||||
toolController.init();
|
||||
|
||||
var paletteController = new pskl.controller.PaletteController();
|
||||
paletteController.init(frameSheet);
|
||||
},
|
||||
|
||||
|
||||
readSizeFromURL_ : function () {
|
||||
var sizeParam = this.readUrlParameter_("size"),
|
||||
size;
|
||||
@ -130,7 +128,7 @@
|
||||
for (i = 0; i < params.length; i++) {
|
||||
val = params[i].split("=");
|
||||
if (val[0] == paramName) {
|
||||
return unescape(val[1]);
|
||||
return window.unescape(val[1]);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
@ -146,12 +144,10 @@
|
||||
frameSheet.load(res.framesheet);
|
||||
pskl.app.animationController.setFPS(res.fps);
|
||||
$.publish(Events.HIDE_NOTIFICATION);
|
||||
pskl.app.finishInit();
|
||||
};
|
||||
|
||||
xhr.onerror = function () {
|
||||
$.publish(Events.HIDE_NOTIFICATION);
|
||||
pskl.app.finishInit();
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
@ -191,7 +187,7 @@
|
||||
if (this.status == 200) {
|
||||
if (pskl.app.isStaticVersion) {
|
||||
var baseUrl = window.location.href.replace(window.location.search, "");
|
||||
window.location.href = baseUrl + "?frameId=" + this.responseText;
|
||||
window.location.href = baseUrl + "?frameId=" + this.responseText;
|
||||
} else {
|
||||
$.publish(Events.SHOW_NOTIFICATION, [{"content": "Successfully saved !"}]);
|
||||
}
|
||||
|
@ -1,36 +1,36 @@
|
||||
(function () {
|
||||
|
||||
var ns = $.namespace("pskl.rendering");
|
||||
ns.CanvasRenderer = function (frame, dpi) {
|
||||
this.frame = frame;
|
||||
this.dpi = dpi;
|
||||
};
|
||||
var ns = $.namespace("pskl.rendering");
|
||||
ns.CanvasRenderer = function (frame, dpi) {
|
||||
this.frame = frame;
|
||||
this.dpi = dpi;
|
||||
};
|
||||
|
||||
ns.CanvasRenderer.prototype.render = function (frame, dpi) {
|
||||
var canvas = this.createCanvas_();
|
||||
var context = canvas.getContext('2d');
|
||||
for(var col = 0, width = this.frame.getWidth(); col < width; col++) {
|
||||
for(var row = 0, height = this.frame.getHeight(); row < height; row++) {
|
||||
var color = this.frame.getPixel(col, row);
|
||||
this.renderPixel_(color, col, row, context);
|
||||
}
|
||||
}
|
||||
ns.CanvasRenderer.prototype.render = function (frame, dpi) {
|
||||
var canvas = this.createCanvas_();
|
||||
var context = canvas.getContext('2d');
|
||||
for(var col = 0, width = this.frame.getWidth(); col < width; col++) {
|
||||
for(var row = 0, height = this.frame.getHeight(); row < height; row++) {
|
||||
var color = this.frame.getPixel(col, row);
|
||||
this.renderPixel_(color, col, row, context);
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
};
|
||||
return context;
|
||||
};
|
||||
|
||||
ns.CanvasRenderer.prototype.renderPixel_ = function (color, col, row, context) {
|
||||
if(color == Constants.TRANSPARENT_COLOR) {
|
||||
color = "#FFF";
|
||||
}
|
||||
ns.CanvasRenderer.prototype.renderPixel_ = function (color, col, row, context) {
|
||||
if(color == Constants.TRANSPARENT_COLOR) {
|
||||
color = "#FFF";
|
||||
}
|
||||
|
||||
context.fillStyle = color;
|
||||
context.fillRect(col * this.dpi, row * this.dpi, this.dpi, this.dpi);
|
||||
};
|
||||
context.fillStyle = color;
|
||||
context.fillRect(col * this.dpi, row * this.dpi, this.dpi, this.dpi);
|
||||
};
|
||||
|
||||
ns.CanvasRenderer.prototype.createCanvas_ = function () {
|
||||
var width = this.frame.getWidth() * this.dpi;
|
||||
var height = this.frame.getHeight() * this.dpi;
|
||||
return pskl.CanvasUtils.createCanvas(width, height);
|
||||
};
|
||||
ns.CanvasRenderer.prototype.createCanvas_ = function () {
|
||||
var width = this.frame.getWidth() * this.dpi;
|
||||
var height = this.frame.getHeight() * this.dpi;
|
||||
return pskl.CanvasUtils.createCanvas(width, height);
|
||||
};
|
||||
})();
|
@ -1,61 +1,61 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.rendering");
|
||||
var ns = $.namespace("pskl.rendering");
|
||||
|
||||
ns.DrawingLoop = function () {
|
||||
this.requestAnimationFrame = this.getRequestAnimationFrameShim_();
|
||||
this.isRunning = false;
|
||||
this.previousTime = 0;
|
||||
this.callbacks = [];
|
||||
};
|
||||
ns.DrawingLoop = function () {
|
||||
this.requestAnimationFrame = this.getRequestAnimationFrameShim_();
|
||||
this.isRunning = false;
|
||||
this.previousTime = 0;
|
||||
this.callbacks = [];
|
||||
};
|
||||
|
||||
ns.DrawingLoop.prototype.addCallback = function (callback, scope, args) {
|
||||
var callbackObj = {
|
||||
fn : callback,
|
||||
scope : scope,
|
||||
args : args
|
||||
};
|
||||
this.callbacks.push(callbackObj);
|
||||
return callbackObj;
|
||||
};
|
||||
ns.DrawingLoop.prototype.addCallback = function (callback, scope, args) {
|
||||
var callbackObj = {
|
||||
fn : callback,
|
||||
scope : scope,
|
||||
args : args
|
||||
};
|
||||
this.callbacks.push(callbackObj);
|
||||
return callbackObj;
|
||||
};
|
||||
|
||||
ns.DrawingLoop.prototype.removeCallback = function (callbackObj) {
|
||||
var index = this.callbacks.indexOf(callbackObj);
|
||||
if (index != -1) {
|
||||
this.callbacks.splice(index, 1);
|
||||
}
|
||||
};
|
||||
ns.DrawingLoop.prototype.removeCallback = function (callbackObj) {
|
||||
var index = this.callbacks.indexOf(callbackObj);
|
||||
if (index != -1) {
|
||||
this.callbacks.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
ns.DrawingLoop.prototype.start = function () {
|
||||
this.isRunning = true;
|
||||
this.loop_();
|
||||
};
|
||||
ns.DrawingLoop.prototype.start = function () {
|
||||
this.isRunning = true;
|
||||
this.loop_();
|
||||
};
|
||||
|
||||
ns.DrawingLoop.prototype.loop_ = function () {
|
||||
var currentTime = Date.now();
|
||||
var delta = currentTime - this.previousTime;
|
||||
this.executeCallbacks_(delta);
|
||||
this.previousTime = currentTime;
|
||||
this.requestAnimationFrame.call(window, this.loop_.bind(this));
|
||||
};
|
||||
ns.DrawingLoop.prototype.loop_ = function () {
|
||||
var currentTime = Date.now();
|
||||
var delta = currentTime - this.previousTime;
|
||||
this.executeCallbacks_(delta);
|
||||
this.previousTime = currentTime;
|
||||
this.requestAnimationFrame.call(window, this.loop_.bind(this));
|
||||
};
|
||||
|
||||
ns.DrawingLoop.prototype.executeCallbacks_ = function (deltaTime) {
|
||||
for (var i = 0 ; i < this.callbacks.length ; i++) {
|
||||
var cb = this.callbacks[i];
|
||||
cb.fn.call(cb.scope, deltaTime, cb.args);
|
||||
}
|
||||
};
|
||||
ns.DrawingLoop.prototype.executeCallbacks_ = function (deltaTime) {
|
||||
for (var i = 0 ; i < this.callbacks.length ; i++) {
|
||||
var cb = this.callbacks[i];
|
||||
cb.fn.call(cb.scope, deltaTime, cb.args);
|
||||
}
|
||||
};
|
||||
|
||||
ns.DrawingLoop.prototype.stop = function () {
|
||||
this.isRunning = false;
|
||||
};
|
||||
ns.DrawingLoop.prototype.stop = function () {
|
||||
this.isRunning = false;
|
||||
};
|
||||
|
||||
ns.DrawingLoop.prototype.getRequestAnimationFrameShim_ = function () {
|
||||
var requestAnimationFrame = window.requestAnimationFrame ||
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
window.msRequestAnimationFrame ||
|
||||
function (callback) { window.setTimeout(callback, 1000/60); };
|
||||
ns.DrawingLoop.prototype.getRequestAnimationFrameShim_ = function () {
|
||||
var requestAnimationFrame = window.requestAnimationFrame ||
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
window.msRequestAnimationFrame ||
|
||||
function (callback) { window.setTimeout(callback, 1000/60); };
|
||||
|
||||
return requestAnimationFrame;
|
||||
};
|
||||
return requestAnimationFrame;
|
||||
};
|
||||
})();
|
@ -1,165 +1,160 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.rendering");
|
||||
var ns = $.namespace("pskl.rendering");
|
||||
|
||||
ns.FrameRenderer = function (container, renderingOptions, className) {
|
||||
this.defaultRenderingOptions = {
|
||||
'supportGridRendering' : false
|
||||
};
|
||||
renderingOptions = $.extend(true, {}, this.defaultRenderingOptions, renderingOptions);
|
||||
ns.FrameRenderer = function (container, renderingOptions, className) {
|
||||
this.defaultRenderingOptions = {
|
||||
'supportGridRendering' : false
|
||||
};
|
||||
renderingOptions = $.extend(true, {}, this.defaultRenderingOptions, renderingOptions);
|
||||
|
||||
if(container === undefined) {
|
||||
throw 'Bad FrameRenderer initialization. <container> undefined.';
|
||||
}
|
||||
if(container === undefined) {
|
||||
throw 'Bad FrameRenderer initialization. <container> undefined.';
|
||||
}
|
||||
|
||||
if(isNaN(renderingOptions.dpi)) {
|
||||
throw 'Bad FrameRenderer initialization. <dpi> not well defined.';
|
||||
}
|
||||
|
||||
this.container = container;
|
||||
this.dpi = renderingOptions.dpi;
|
||||
this.className = className;
|
||||
this.canvas = null;
|
||||
this.supportGridRendering = renderingOptions.supportGridRendering;
|
||||
|
||||
this.enableGrid(pskl.UserSettings.get(pskl.UserSettings.SHOW_GRID));
|
||||
|
||||
// Flag to know if the config was altered
|
||||
this.canvasConfigDirty = true;
|
||||
this.updateBackgroundClass_(pskl.UserSettings.get(pskl.UserSettings.CANVAS_BACKGROUND));
|
||||
$.subscribe(Events.USER_SETTINGS_CHANGED, $.proxy(this.onUserSettingsChange_, this));
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.updateDPI = function (newDPI) {
|
||||
this.dpi = newDPI;
|
||||
this.canvasConfigDirty = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.FrameRenderer.prototype.onUserSettingsChange_ = function (evt, settingName, settingValue) {
|
||||
|
||||
if(settingName == pskl.UserSettings.SHOW_GRID) {
|
||||
this.enableGrid(settingValue);
|
||||
}
|
||||
else if (settingName == pskl.UserSettings.CANVAS_BACKGROUND) {
|
||||
this.updateBackgroundClass_(settingValue);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.FrameRenderer.prototype.updateBackgroundClass_ = function (newClass) {
|
||||
var currentClass = this.container.data('current-background-class');
|
||||
if (currentClass) {
|
||||
this.container.removeClass(currentClass);
|
||||
}
|
||||
this.container.addClass(newClass);
|
||||
this.container.data('current-background-class', newClass);
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.enableGrid = function (flag) {
|
||||
this.gridStrokeWidth = (flag && this.supportGridRendering) ? Constants.GRID_STROKE_WIDTH : 0;
|
||||
this.canvasConfigDirty = true;
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.render = function (frame) {
|
||||
this.clear(frame);
|
||||
var context = this.getCanvas_(frame).getContext('2d');
|
||||
for(var col = 0, width = frame.getWidth(); col < width; col++) {
|
||||
for(var row = 0, height = frame.getHeight(); row < height; row++) {
|
||||
var color = frame.getPixel(col, row);
|
||||
this.renderPixel_(color, col, row, context);
|
||||
}
|
||||
}
|
||||
this.lastRenderedFrame = frame;
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.renderPixel_ = function (color, col, row, context) {
|
||||
if(color != Constants.TRANSPARENT_COLOR) {
|
||||
context.fillStyle = color;
|
||||
context.fillRect(this.getFramePos_(col), this.getFramePos_(row), this.dpi, this.dpi);
|
||||
}
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.clear = function (frame) {
|
||||
var canvas = this.getCanvas_(frame);
|
||||
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
|
||||
};
|
||||
|
||||
/**
|
||||
* Transform a screen pixel-based coordinate (relative to the top-left corner of the rendered
|
||||
* frame) into a sprite coordinate in column and row.
|
||||
* @public
|
||||
*/
|
||||
ns.FrameRenderer.prototype.convertPixelCoordinatesIntoSpriteCoordinate = function(coords) {
|
||||
var cellSize = this.dpi + this.gridStrokeWidth;
|
||||
return {
|
||||
"col" : (coords.x - coords.x % cellSize) / cellSize,
|
||||
"row" : (coords.y - coords.y % cellSize) / cellSize
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.FrameRenderer.prototype.getFramePos_ = function(index) {
|
||||
return index * this.dpi + ((index - 1) * this.gridStrokeWidth);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.FrameRenderer.prototype.drawGrid_ = function(canvas, width, height, col, row) {
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.lineWidth = Constants.GRID_STROKE_WIDTH;
|
||||
ctx.strokeStyle = Constants.GRID_STROKE_COLOR;
|
||||
for(var c=1; c < col; c++) {
|
||||
ctx.moveTo(this.getFramePos_(c), 0);
|
||||
ctx.lineTo(this.getFramePos_(c), height);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
for(var r=1; r < row; r++) {
|
||||
ctx.moveTo(0, this.getFramePos_(r));
|
||||
ctx.lineTo(width, this.getFramePos_(r));
|
||||
ctx.stroke();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.FrameRenderer.prototype.getCanvas_ = function (frame) {
|
||||
if(this.canvasConfigDirty) {
|
||||
$(this.canvas).remove();
|
||||
|
||||
var col = frame.getWidth(),
|
||||
row = frame.getHeight();
|
||||
|
||||
var pixelWidth = col * this.dpi + this.gridStrokeWidth * (col - 1);
|
||||
var pixelHeight = row * this.dpi + this.gridStrokeWidth * (row - 1);
|
||||
var classes = ['canvas'];
|
||||
if (this.className) {
|
||||
classes.push(this.className);
|
||||
}
|
||||
var canvas = pskl.CanvasUtils.createCanvas(pixelWidth, pixelHeight, classes);
|
||||
|
||||
this.container.append(canvas);
|
||||
|
||||
if(this.gridStrokeWidth > 0) {
|
||||
this.drawGrid_(canvas, pixelWidth, pixelHeight, col, row);
|
||||
}
|
||||
|
||||
if(isNaN(renderingOptions.dpi)) {
|
||||
throw 'Bad FrameRenderer initialization. <dpi> not well defined.';
|
||||
}
|
||||
|
||||
this.container = container;
|
||||
this.dpi = renderingOptions.dpi;
|
||||
this.className = className;
|
||||
this.canvas = null;
|
||||
this.supportGridRendering = renderingOptions.supportGridRendering;
|
||||
|
||||
this.enableGrid(pskl.UserSettings.get(pskl.UserSettings.SHOW_GRID));
|
||||
|
||||
// Flag to know if the config was altered
|
||||
this.canvasConfigDirty = true;
|
||||
this.updateBackgroundClass_(pskl.UserSettings.get(pskl.UserSettings.CANVAS_BACKGROUND));
|
||||
$.subscribe(Events.USER_SETTINGS_CHANGED, $.proxy(this.onUserSettingsChange_, this));
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.init = function (frame) {
|
||||
this.render(frame);
|
||||
this.lastRenderedFrame = frame;
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.updateDPI = function (newDPI) {
|
||||
this.dpi = newDPI;
|
||||
this.canvasConfigDirty = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.FrameRenderer.prototype.onUserSettingsChange_ = function (evt, settingName, settingValue) {
|
||||
|
||||
if(settingName == pskl.UserSettings.SHOW_GRID) {
|
||||
this.enableGrid(settingValue);
|
||||
}
|
||||
else if (settingName == pskl.UserSettings.CANVAS_BACKGROUND) {
|
||||
this.updateBackgroundClass_(settingValue);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.FrameRenderer.prototype.updateBackgroundClass_ = function (newClass) {
|
||||
var currentClass = this.container.data('current-background-class');
|
||||
if (currentClass) {
|
||||
this.container.removeClass(currentClass);
|
||||
}
|
||||
this.container.addClass(newClass);
|
||||
this.container.data('current-background-class', newClass);
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.enableGrid = function (flag) {
|
||||
this.gridStrokeWidth = (flag && this.supportGridRendering) ? Constants.GRID_STROKE_WIDTH : 0;
|
||||
this.canvasConfigDirty = true;
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.render = function (frame) {
|
||||
this.clear(frame);
|
||||
var context = this.getCanvas_(frame).getContext('2d');
|
||||
for(var col = 0, width = frame.getWidth(); col < width; col++) {
|
||||
for(var row = 0, height = frame.getHeight(); row < height; row++) {
|
||||
var color = frame.getPixel(col, row);
|
||||
this.renderPixel_(color, col, row, context);
|
||||
}
|
||||
}
|
||||
this.lastRenderedFrame = frame;
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.renderPixel_ = function (color, col, row, context) {
|
||||
if(color != Constants.TRANSPARENT_COLOR) {
|
||||
context.fillStyle = color;
|
||||
context.fillRect(this.getFramePos_(col), this.getFramePos_(row), this.dpi, this.dpi);
|
||||
}
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.clear = function (frame) {
|
||||
var canvas = this.getCanvas_(frame);
|
||||
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
|
||||
};
|
||||
|
||||
/**
|
||||
* Transform a screen pixel-based coordinate (relative to the top-left corner of the rendered
|
||||
* frame) into a sprite coordinate in column and row.
|
||||
* @public
|
||||
*/
|
||||
ns.FrameRenderer.prototype.convertPixelCoordinatesIntoSpriteCoordinate = function(coords) {
|
||||
var cellSize = this.dpi + this.gridStrokeWidth;
|
||||
return {
|
||||
"col" : (coords.x - coords.x % cellSize) / cellSize,
|
||||
"row" : (coords.y - coords.y % cellSize) / cellSize
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.FrameRenderer.prototype.getFramePos_ = function(index) {
|
||||
return index * this.dpi + ((index - 1) * this.gridStrokeWidth);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.FrameRenderer.prototype.drawGrid_ = function(canvas, width, height, col, row) {
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.lineWidth = Constants.GRID_STROKE_WIDTH;
|
||||
ctx.strokeStyle = Constants.GRID_STROKE_COLOR;
|
||||
for(var c=1; c < col; c++) {
|
||||
ctx.moveTo(this.getFramePos_(c), 0);
|
||||
ctx.lineTo(this.getFramePos_(c), height);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
for(var r=1; r < row; r++) {
|
||||
ctx.moveTo(0, this.getFramePos_(r));
|
||||
ctx.lineTo(width, this.getFramePos_(r));
|
||||
ctx.stroke();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.FrameRenderer.prototype.getCanvas_ = function (frame) {
|
||||
if(this.canvasConfigDirty) {
|
||||
$(this.canvas).remove();
|
||||
|
||||
var col = frame.getWidth(),
|
||||
row = frame.getHeight();
|
||||
|
||||
var pixelWidth = col * this.dpi + this.gridStrokeWidth * (col - 1);
|
||||
var pixelHeight = row * this.dpi + this.gridStrokeWidth * (row - 1);
|
||||
var classes = ['canvas'];
|
||||
if (this.className) {
|
||||
classes.push(this.className);
|
||||
}
|
||||
var canvas = pskl.CanvasUtils.createCanvas(pixelWidth, pixelHeight, classes);
|
||||
|
||||
this.container.append(canvas);
|
||||
|
||||
if(this.gridStrokeWidth > 0) {
|
||||
this.drawGrid_(canvas, pixelWidth, pixelHeight, col, row);
|
||||
}
|
||||
|
||||
this.canvas = canvas;
|
||||
this.canvasConfigDirty = false;
|
||||
}
|
||||
return this.canvas;
|
||||
};
|
||||
this.canvas = canvas;
|
||||
this.canvasConfigDirty = false;
|
||||
}
|
||||
return this.canvas;
|
||||
};
|
||||
})();
|
@ -1,63 +1,63 @@
|
||||
(function () {
|
||||
|
||||
var ns = $.namespace("pskl.rendering");
|
||||
var ns = $.namespace("pskl.rendering");
|
||||
|
||||
ns.SpritesheetRenderer = function (framesheet) {
|
||||
this.framesheet = framesheet;
|
||||
};
|
||||
ns.SpritesheetRenderer = function (framesheet) {
|
||||
this.framesheet = framesheet;
|
||||
};
|
||||
|
||||
ns.SpritesheetRenderer.prototype.renderAsImageDataSpritesheetPNG = function () {
|
||||
var canvas = this.createCanvas_();
|
||||
for (var i = 0 ; i < this.framesheet.getFrameCount() ; i++) {
|
||||
var frame = this.framesheet.getFrameByIndex(i);
|
||||
this.drawFrameInCanvas_(frame, canvas, i * this.framesheet.getWidth(), 0);
|
||||
}
|
||||
return canvas.toDataURL("image/png");
|
||||
};
|
||||
ns.SpritesheetRenderer.prototype.renderAsImageDataSpritesheetPNG = function () {
|
||||
var canvas = this.createCanvas_();
|
||||
for (var i = 0 ; i < this.framesheet.getFrameCount() ; i++) {
|
||||
var frame = this.framesheet.getFrameByIndex(i);
|
||||
this.drawFrameInCanvas_(frame, canvas, i * this.framesheet.getWidth(), 0);
|
||||
}
|
||||
return canvas.toDataURL("image/png");
|
||||
};
|
||||
|
||||
ns.SpritesheetRenderer.prototype.renderAsImageDataAnimatedGIF = function (fps) {
|
||||
var encoder = new GIFEncoder(), dpi = 10;
|
||||
encoder.setRepeat(0);
|
||||
encoder.setDelay(1000/fps);
|
||||
ns.SpritesheetRenderer.prototype.renderAsImageDataAnimatedGIF = function (fps) {
|
||||
var encoder = new window.GIFEncoder(), dpi = 10;
|
||||
encoder.setRepeat(0);
|
||||
encoder.setDelay(1000/fps);
|
||||
|
||||
encoder.start();
|
||||
encoder.setSize(this.framesheet.getWidth() * dpi, this.framesheet.getHeight() * dpi);
|
||||
for (var i = 0 ; i < this.framesheet.frames.length ; i++) {
|
||||
var frame = this.framesheet.frames[i];
|
||||
var renderer = new pskl.rendering.CanvasRenderer(frame, dpi);
|
||||
encoder.addFrame(renderer.render());
|
||||
encoder.start();
|
||||
encoder.setSize(this.framesheet.getWidth() * dpi, this.framesheet.getHeight() * dpi);
|
||||
for (var i = 0 ; i < this.framesheet.frames.length ; i++) {
|
||||
var frame = this.framesheet.frames[i];
|
||||
var renderer = new pskl.rendering.CanvasRenderer(frame, dpi);
|
||||
encoder.addFrame(renderer.render());
|
||||
}
|
||||
encoder.finish();
|
||||
|
||||
var imageData = 'data:image/gif;base64,' + window.encode64(encoder.stream().getData());
|
||||
return imageData;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* TODO(juliandescottes): Mutualize with code already present in FrameRenderer
|
||||
*/
|
||||
ns.SpritesheetRenderer.prototype.drawFrameInCanvas_ = function (frame, canvas, offsetWidth, offsetHeight) {
|
||||
var context = canvas.getContext('2d');
|
||||
for(var col = 0, width = frame.getWidth(); col < width; col++) {
|
||||
for(var row = 0, height = frame.getHeight(); row < height; row++) {
|
||||
var color = frame.getPixel(col, row);
|
||||
if(color != Constants.TRANSPARENT_COLOR) {
|
||||
context.fillStyle = color;
|
||||
context.fillRect(col + offsetWidth, row + offsetHeight, 1, 1);
|
||||
}
|
||||
encoder.finish();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var imageData = 'data:image/gif;base64,' + encode64(encoder.stream().getData());
|
||||
return imageData;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* TODO(juliandescottes): Mutualize with code already present in FrameRenderer
|
||||
*/
|
||||
ns.SpritesheetRenderer.prototype.drawFrameInCanvas_ = function (frame, canvas, offsetWidth, offsetHeight) {
|
||||
var context = canvas.getContext('2d');
|
||||
for(var col = 0, width = frame.getWidth(); col < width; col++) {
|
||||
for(var row = 0, height = frame.getHeight(); row < height; row++) {
|
||||
var color = frame.getPixel(col, row);
|
||||
if(color != Constants.TRANSPARENT_COLOR) {
|
||||
context.fillStyle = color;
|
||||
context.fillRect(col + offsetWidth, row + offsetHeight, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ns.SpritesheetRenderer.prototype.createCanvas_ = function () {
|
||||
var frameCount = this.framesheet.getFrameCount();
|
||||
if (frameCount > 0){
|
||||
var width = frameCount * this.framesheet.getWidth();
|
||||
var height = this.framesheet.getHeight();
|
||||
return pskl.CanvasUtils.createCanvas(width, height);
|
||||
} else {
|
||||
throw "Cannot render empty Spritesheet";
|
||||
}
|
||||
};
|
||||
ns.SpritesheetRenderer.prototype.createCanvas_ = function () {
|
||||
var frameCount = this.framesheet.getFrameCount();
|
||||
if (frameCount > 0){
|
||||
var width = frameCount * this.framesheet.getWidth();
|
||||
var height = this.framesheet.getHeight();
|
||||
return pskl.CanvasUtils.createCanvas(width, height);
|
||||
} else {
|
||||
throw "Cannot render empty Spritesheet";
|
||||
}
|
||||
};
|
||||
})();
|
@ -1,34 +1,34 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.selection");
|
||||
var ns = $.namespace("pskl.selection");
|
||||
|
||||
ns.BaseSelection = function () {
|
||||
this.reset();
|
||||
};
|
||||
ns.BaseSelection = function () {
|
||||
this.reset();
|
||||
};
|
||||
|
||||
ns.BaseSelection.prototype.reset = function () {
|
||||
this.pixels = [];
|
||||
this.hasPastedContent = false;
|
||||
};
|
||||
ns.BaseSelection.prototype.reset = function () {
|
||||
this.pixels = [];
|
||||
this.hasPastedContent = false;
|
||||
};
|
||||
|
||||
ns.BaseSelection.prototype.move = function (colDiff, rowDiff) {
|
||||
var movedPixel, movedPixels = [];
|
||||
ns.BaseSelection.prototype.move = function (colDiff, rowDiff) {
|
||||
var movedPixel, movedPixels = [];
|
||||
|
||||
for(var i=0, l=this.pixels.length; i<l; i++) {
|
||||
movedPixel = this.pixels[i];
|
||||
movedPixel.col += colDiff;
|
||||
movedPixel.row += rowDiff;
|
||||
movedPixels.push(movedPixel);
|
||||
}
|
||||
this.pixels = movedPixels;
|
||||
};
|
||||
for(var i=0, l=this.pixels.length; i<l; i++) {
|
||||
movedPixel = this.pixels[i];
|
||||
movedPixel.col += colDiff;
|
||||
movedPixel.row += rowDiff;
|
||||
movedPixels.push(movedPixel);
|
||||
}
|
||||
this.pixels = movedPixels;
|
||||
};
|
||||
|
||||
ns.BaseSelection.prototype.fillSelectionFromFrame = function (targetFrame) {
|
||||
var pixelWithCopiedColor;
|
||||
for(var i=0, l=this.pixels.length; i<l; i++) {
|
||||
pixelWithCopiedColor = this.pixels[i];
|
||||
pixelWithCopiedColor.copiedColor =
|
||||
targetFrame.getPixel(pixelWithCopiedColor.col, pixelWithCopiedColor.row);
|
||||
}
|
||||
this.hasPastedContent = true;
|
||||
};
|
||||
ns.BaseSelection.prototype.fillSelectionFromFrame = function (targetFrame) {
|
||||
var pixelWithCopiedColor;
|
||||
for(var i=0, l=this.pixels.length; i<l; i++) {
|
||||
pixelWithCopiedColor = this.pixels[i];
|
||||
pixelWithCopiedColor.copiedColor =
|
||||
targetFrame.getPixel(pixelWithCopiedColor.col, pixelWithCopiedColor.row);
|
||||
}
|
||||
this.hasPastedContent = true;
|
||||
};
|
||||
})();
|
@ -1,9 +1,9 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.selection");
|
||||
var ns = $.namespace("pskl.selection");
|
||||
|
||||
ns.RectangularSelection = function (x0, y0, x1, y1) {
|
||||
this.pixels = pskl.PixelUtils.getRectanglePixels(x0, y0, x1, y1);
|
||||
};
|
||||
ns.RectangularSelection = function (x0, y0, x1, y1) {
|
||||
this.pixels = pskl.PixelUtils.getRectanglePixels(x0, y0, x1, y1);
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.RectangularSelection, ns.BaseSelection);
|
||||
pskl.utils.inherit(ns.RectangularSelection, ns.BaseSelection);
|
||||
})();
|
@ -1,130 +1,124 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.selection");
|
||||
var ns = $.namespace("pskl.selection");
|
||||
|
||||
|
||||
ns.SelectionManager = function (framesheet, overlayFrame) {
|
||||
|
||||
this.framesheet = framesheet;
|
||||
this.overlayFrame = overlayFrame;
|
||||
|
||||
this.currentSelection = null;
|
||||
|
||||
$.subscribe(Events.SELECTION_CREATED, $.proxy(this.onSelectionCreated_, this));
|
||||
$.subscribe(Events.SELECTION_DISMISSED, $.proxy(this.onSelectionDismissed_, this));
|
||||
$.subscribe(Events.SELECTION_MOVE_REQUEST, $.proxy(this.onSelectionMoved_, this));
|
||||
|
||||
$.subscribe(Events.PASTE, $.proxy(this.onPaste_, this));
|
||||
$.subscribe(Events.COPY, $.proxy(this.onCopy_, this));
|
||||
$.subscribe(Events.CUT, $.proxy(this.onCut_, this));
|
||||
ns.SelectionManager = function (framesheet) {
|
||||
|
||||
this.framesheet = framesheet;
|
||||
|
||||
this.currentSelection = null;
|
||||
};
|
||||
|
||||
$.subscribe(Events.TOOL_SELECTED, $.proxy(this.onToolSelected_, this));
|
||||
};
|
||||
ns.SelectionManager.prototype.init = function () {
|
||||
$.subscribe(Events.SELECTION_CREATED, $.proxy(this.onSelectionCreated_, this));
|
||||
$.subscribe(Events.SELECTION_DISMISSED, $.proxy(this.onSelectionDismissed_, this));
|
||||
$.subscribe(Events.SELECTION_MOVE_REQUEST, $.proxy(this.onSelectionMoved_, this));
|
||||
|
||||
$.subscribe(Events.PASTE, $.proxy(this.onPaste_, this));
|
||||
$.subscribe(Events.COPY, $.proxy(this.onCopy_, this));
|
||||
$.subscribe(Events.CUT, $.proxy(this.onCut_, this));
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.SelectionManager.prototype.cleanSelection_ = function(selection) {
|
||||
if(this.currentSelection) {
|
||||
this.currentSelection.reset();
|
||||
}
|
||||
this.overlayFrame.clear();
|
||||
};
|
||||
$.subscribe(Events.TOOL_SELECTED, $.proxy(this.onToolSelected_, this));
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.SelectionManager.prototype.onToolSelected_ = function(evt, tool) {
|
||||
var isSelectionTool = tool instanceof pskl.drawingtools.BaseSelect;
|
||||
if(!isSelectionTool) {
|
||||
this.cleanSelection_();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.SelectionManager.prototype.cleanSelection_ = function() {
|
||||
if(this.currentSelection) {
|
||||
this.currentSelection.reset();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.SelectionManager.prototype.onSelectionDismissed_ = function(evt) {
|
||||
this.cleanSelection_();
|
||||
};
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.SelectionManager.prototype.onToolSelected_ = function(evt, tool) {
|
||||
var isSelectionTool = tool instanceof pskl.drawingtools.BaseSelect;
|
||||
if(!isSelectionTool) {
|
||||
this.cleanSelection_();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.SelectionManager.prototype.onCut_ = function(evt) {
|
||||
if(this.currentSelection) {
|
||||
// Put cut target into the selection:
|
||||
this.currentSelection.fillSelectionFromFrame(this.framesheet.getCurrentFrame());
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.SelectionManager.prototype.onSelectionDismissed_ = function(evt) {
|
||||
this.cleanSelection_();
|
||||
};
|
||||
|
||||
var pixels = this.currentSelection.pixels;
|
||||
var currentFrame = this.framesheet.getCurrentFrame();
|
||||
for(var i=0, l=pixels.length; i<l; i++) {
|
||||
try {
|
||||
currentFrame.setPixel(pixels[i].col, pixels[i].row, Constants.TRANSPARENT_COLOR);
|
||||
}
|
||||
catch(e) {
|
||||
// Catchng out of frame's bound pixels without testing
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw "Bad state for CUT callback in SelectionManager";
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.SelectionManager.prototype.onCut_ = function(evt) {
|
||||
if(this.currentSelection) {
|
||||
// Put cut target into the selection:
|
||||
this.currentSelection.fillSelectionFromFrame(this.framesheet.getCurrentFrame());
|
||||
|
||||
ns.SelectionManager.prototype.onPaste_ = function(evt) {
|
||||
if(this.currentSelection && this.currentSelection.hasPastedContent) {
|
||||
var pixels = this.currentSelection.pixels;
|
||||
var currentFrame = this.framesheet.getCurrentFrame();
|
||||
for(var i=0, l=pixels.length; i<l; i++) {
|
||||
try {
|
||||
currentFrame.setPixel(
|
||||
pixels[i].col, pixels[i].row,
|
||||
pixels[i].copiedColor);
|
||||
}
|
||||
catch(e) {
|
||||
// Catchng out of frame's bound pixels without testing
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var pixels = this.currentSelection.pixels;
|
||||
var currentFrame = this.framesheet.getCurrentFrame();
|
||||
for(var i=0, l=pixels.length; i<l; i++) {
|
||||
try {
|
||||
currentFrame.setPixel(pixels[i].col, pixels[i].row, Constants.TRANSPARENT_COLOR);
|
||||
}
|
||||
catch(e) {
|
||||
// Catchng out of frame's bound pixels without testing
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw "Bad state for CUT callback in SelectionManager";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.SelectionManager.prototype.onCopy_ = function(evt) {
|
||||
if(this.currentSelection && this.framesheet.getCurrentFrame()) {
|
||||
this.currentSelection.fillSelectionFromFrame(this.framesheet.getCurrentFrame());
|
||||
}
|
||||
else {
|
||||
throw "Bad state for CUT callback in SelectionManager";
|
||||
}
|
||||
};
|
||||
ns.SelectionManager.prototype.onPaste_ = function(evt) {
|
||||
if(this.currentSelection && this.currentSelection.hasPastedContent) {
|
||||
var pixels = this.currentSelection.pixels;
|
||||
var currentFrame = this.framesheet.getCurrentFrame();
|
||||
for(var i=0, l=pixels.length; i<l; i++) {
|
||||
try {
|
||||
currentFrame.setPixel(
|
||||
pixels[i].col, pixels[i].row,
|
||||
pixels[i].copiedColor);
|
||||
}
|
||||
catch(e) {
|
||||
// Catchng out of frame's bound pixels without testing
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.SelectionManager.prototype.onSelectionCreated_ = function(evt, selection) {
|
||||
if(selection) {
|
||||
this.currentSelection = selection;
|
||||
var pixels = selection.pixels;
|
||||
for(var i=0, l=pixels.length; i<l; i++) {
|
||||
this.overlayFrame.setPixel(pixels[i].col, pixels[i].row, Constants.SELECTION_TRANSPARENT_COLOR);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw "No selection set in SelectionManager";
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.SelectionManager.prototype.onCopy_ = function(evt) {
|
||||
if(this.currentSelection && this.framesheet.getCurrentFrame()) {
|
||||
this.currentSelection.fillSelectionFromFrame(this.framesheet.getCurrentFrame());
|
||||
}
|
||||
else {
|
||||
throw "Bad state for CUT callback in SelectionManager";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.SelectionManager.prototype.onSelectionMoved_ = function(evt, colDiff, rowDiff) {
|
||||
if(this.currentSelection) {
|
||||
this.currentSelection.move(colDiff, rowDiff);
|
||||
}
|
||||
else {
|
||||
throw "Bad state: No currentSelection set when trying to move it in SelectionManager";
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.SelectionManager.prototype.onSelectionCreated_ = function(evt, selection) {
|
||||
if(selection) {
|
||||
this.currentSelection = selection;
|
||||
} else {
|
||||
throw "No selection set in SelectionManager";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.SelectionManager.prototype.onSelectionMoved_ = function(evt, colDiff, rowDiff) {
|
||||
if(this.currentSelection) {
|
||||
this.currentSelection.move(colDiff, rowDiff);
|
||||
}
|
||||
else {
|
||||
throw "Bad state: No currentSelection set when trying to move it in SelectionManager";
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
@ -1,9 +1,9 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.selection");
|
||||
var ns = $.namespace("pskl.selection");
|
||||
|
||||
ns.ShapeSelection = function (pixels) {
|
||||
this.pixels = pixels;
|
||||
};
|
||||
ns.ShapeSelection = function (pixels) {
|
||||
this.pixels = pixels;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.ShapeSelection, ns.BaseSelection);
|
||||
pskl.utils.inherit(ns.ShapeSelection, ns.BaseSelection);
|
||||
})();
|
@ -1,15 +1,15 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.service");
|
||||
ns.HistoryService = function (framesheet) {
|
||||
var ns = $.namespace("pskl.service");
|
||||
ns.HistoryService = function (framesheet) {
|
||||
this.framesheet = framesheet;
|
||||
};
|
||||
|
||||
ns.HistoryService.prototype.init = function () {
|
||||
ns.HistoryService.prototype.init = function () {
|
||||
|
||||
$.subscribe(Events.TOOL_RELEASED, this.saveState.bind(this));
|
||||
$.subscribe(Events.UNDO, this.undo.bind(this));
|
||||
$.subscribe(Events.REDO, this.redo.bind(this));
|
||||
};
|
||||
};
|
||||
|
||||
ns.HistoryService.prototype.saveState = function () {
|
||||
this.framesheet.getCurrentFrame().saveState();
|
||||
|
@ -1,64 +1,64 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.service");
|
||||
var ns = $.namespace("pskl.service");
|
||||
|
||||
ns.KeyboardEventService = function () {};
|
||||
ns.KeyboardEventService = function () {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.KeyboardEventService.prototype.KeyboardActions_ = {
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.KeyboardEventService.prototype.KeyboardActions_ = {
|
||||
|
||||
"ctrl" : {
|
||||
"z" : Events.UNDO,
|
||||
"y" : Events.REDO,
|
||||
"x" : Events.CUT,
|
||||
"c" : Events.COPY,
|
||||
"v" : Events.PASTE
|
||||
}
|
||||
};
|
||||
"ctrl" : {
|
||||
"z" : Events.UNDO,
|
||||
"y" : Events.REDO,
|
||||
"x" : Events.CUT,
|
||||
"c" : Events.COPY,
|
||||
"v" : Events.PASTE
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.KeyboardEventService.prototype.CharCodeToKeyCodeMap_ = {
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.KeyboardEventService.prototype.CharCodeToKeyCodeMap_ = {
|
||||
|
||||
90 : "z",
|
||||
89 : "y",
|
||||
88 : "x",
|
||||
67 : "c",
|
||||
86 : "v"
|
||||
};
|
||||
90 : "z",
|
||||
89 : "y",
|
||||
88 : "x",
|
||||
67 : "c",
|
||||
86 : "v"
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.KeyboardEventService.prototype.onKeyUp_ = function(evt) {
|
||||
var isMac = false;
|
||||
if (navigator.appVersion.indexOf("Mac")!=-1) {
|
||||
// Welcome in mac world where vowels are consons and meta used instead of ctrl:
|
||||
isMac = true;
|
||||
}
|
||||
|
||||
if (isMac ? evt.metaKey : evt.ctrlKey) {
|
||||
// Get key pressed:
|
||||
var letter = this.CharCodeToKeyCodeMap_[evt.which];
|
||||
if(letter) {
|
||||
var eventToTrigger = this.KeyboardActions_.ctrl[letter];
|
||||
if(eventToTrigger) {
|
||||
$.publish(eventToTrigger);
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.KeyboardEventService.prototype.onKeyUp_ = function(evt) {
|
||||
var isMac = false;
|
||||
if (navigator.appVersion.indexOf("Mac")!=-1) {
|
||||
// Welcome in mac world where vowels are consons and meta used instead of ctrl:
|
||||
isMac = true;
|
||||
}
|
||||
|
||||
if (isMac ? evt.metaKey : evt.ctrlKey) {
|
||||
// Get key pressed:
|
||||
var letter = this.CharCodeToKeyCodeMap_[evt.which];
|
||||
if(letter) {
|
||||
var eventToTrigger = this.KeyboardActions_.ctrl[letter];
|
||||
if(eventToTrigger) {
|
||||
$.publish(eventToTrigger);
|
||||
|
||||
evt.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
evt.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.KeyboardEventService.prototype.init = function() {
|
||||
$(document.body).keydown($.proxy(this.onKeyUp_, this));
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.KeyboardEventService.prototype.init = function() {
|
||||
$(document.body).keydown($.proxy(this.onKeyUp_, this));
|
||||
};
|
||||
|
||||
})();
|
@ -4,7 +4,7 @@
|
||||
ns.LocalStorageService = function (framesheet_) {
|
||||
|
||||
if(framesheet_ === undefined) {
|
||||
throw "Bad LocalStorageService initialization: <undefined frameSheet>";
|
||||
throw "Bad LocalStorageService initialization: <undefined frameSheet>";
|
||||
}
|
||||
this.framesheet = framesheet_;
|
||||
this.localStorageThrottler_ = null;
|
||||
|
@ -1,22 +1,22 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl");
|
||||
var ns = $.namespace("pskl");
|
||||
|
||||
ns.CanvasUtils = {
|
||||
createCanvas : function (width, height, classList) {
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.setAttribute("width", width);
|
||||
canvas.setAttribute("height", height);
|
||||
ns.CanvasUtils = {
|
||||
createCanvas : function (width, height, classList) {
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.setAttribute("width", width);
|
||||
canvas.setAttribute("height", height);
|
||||
|
||||
if (typeof classList == "string") {
|
||||
classList = [classList];
|
||||
}
|
||||
if (Array.isArray(classList)) {
|
||||
for (var i = 0 ; i < classList.length ; i++) {
|
||||
canvas.classList.add(classList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return canvas;
|
||||
}
|
||||
};
|
||||
if (typeof classList == "string") {
|
||||
classList = [classList];
|
||||
}
|
||||
if (Array.isArray(classList)) {
|
||||
for (var i = 0 ; i < classList.length ; i++) {
|
||||
canvas.classList.add(classList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return canvas;
|
||||
}
|
||||
};
|
||||
})();
|
@ -1,175 +1,177 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl");
|
||||
var ns = $.namespace("pskl");
|
||||
|
||||
ns.PixelUtils = {
|
||||
ns.PixelUtils = {
|
||||
|
||||
getRectanglePixels : function (x0, y0, x1, y1) {
|
||||
var rectangle = this.getOrderedRectangleCoordinates(x0, y0, x1, y1);
|
||||
var pixels = [];
|
||||
getRectanglePixels : function (x0, y0, x1, y1) {
|
||||
var rectangle = this.getOrderedRectangleCoordinates(x0, y0, x1, y1);
|
||||
var pixels = [];
|
||||
|
||||
for(var x = rectangle.x0; x <= rectangle.x1; x++) {
|
||||
for(var y = rectangle.y0; y <= rectangle.y1; y++) {
|
||||
pixels.push({"col": x, "row": y});
|
||||
}
|
||||
for(var x = rectangle.x0; x <= rectangle.x1; x++) {
|
||||
for(var y = rectangle.y0; y <= rectangle.y1; y++) {
|
||||
pixels.push({"col": x, "row": y});
|
||||
}
|
||||
}
|
||||
|
||||
return pixels;
|
||||
},
|
||||
|
||||
getBoundRectanglePixels : function (x0, y0, x1, y1) {
|
||||
var rectangle = this.getOrderedRectangleCoordinates(x0, y0, x1, y1);
|
||||
var pixels = [];
|
||||
// Creating horizontal sides of the rectangle:
|
||||
for(var x = rectangle.x0; x <= rectangle.x1; x++) {
|
||||
pixels.push({"col": x, "row": rectangle.y0});
|
||||
pixels.push({"col": x, "row": rectangle.y1});
|
||||
}
|
||||
|
||||
// Creating vertical sides of the rectangle:
|
||||
for(var y = rectangle.y0; y <= rectangle.y1; y++) {
|
||||
pixels.push({"col": rectangle.x0, "row": y});
|
||||
pixels.push({"col": rectangle.x1, "row": y});
|
||||
}
|
||||
|
||||
return pixels;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return an object of ordered rectangle coordinate.
|
||||
* In returned object {x0, y0} => top left corner - {x1, y1} => bottom right corner
|
||||
* @private
|
||||
*/
|
||||
getOrderedRectangleCoordinates : function (x0, y0, x1, y1) {
|
||||
return {
|
||||
x0 : Math.min(x0, x1),
|
||||
y0 : Math.min(y0, y1),
|
||||
x1 : Math.max(x0, x1),
|
||||
y1 : Math.max(y0, y1),
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the list of pixels that would have been filled by a paintbucket tool applied
|
||||
* on pixel at coordinate (x,y).
|
||||
* This function is not altering the Frame object argument.
|
||||
*
|
||||
* @param frame pskl.model.Frame The frame target in which we want to paintbucket
|
||||
* @param col number Column coordinate in the frame
|
||||
* @param row number Row coordinate in the frame
|
||||
*
|
||||
* @return an array of the pixel coordinates paint with the replacement color
|
||||
*/
|
||||
getSimilarConnectedPixelsFromFrame: function(frame, col, row) {
|
||||
// To get the list of connected (eg the same color) pixels, we will use the paintbucket algorithm
|
||||
// in a fake cloned frame. The returned pixels by the paintbucket algo are the painted pixels
|
||||
// and are as well connected.
|
||||
var fakeFrame = frame.clone(); // We just want to
|
||||
var fakeFillColor = "sdfsdfsdf"; // A fake color that will never match a real color.
|
||||
var paintedPixels = this.paintSimilarConnectedPixelsFromFrame(fakeFrame, col, row, fakeFillColor);
|
||||
|
||||
return paintedPixels;
|
||||
},
|
||||
|
||||
/**
|
||||
* Apply the paintbucket tool in a frame at the (col, row) initial position
|
||||
* with the replacement color.
|
||||
*
|
||||
* @param frame pskl.model.Frame The frame target in which we want to paintbucket
|
||||
* @param col number Column coordinate in the frame
|
||||
* @param row number Row coordinate in the frame
|
||||
* @param replacementColor string Hexadecimal color used to fill the area
|
||||
*
|
||||
* @return an array of the pixel coordinates paint with the replacement color
|
||||
*/
|
||||
paintSimilarConnectedPixelsFromFrame: function(frame, col, row, replacementColor) {
|
||||
/**
|
||||
* Queue linear Flood-fill (node, target-color, replacement-color):
|
||||
* 1. Set Q to the empty queue.
|
||||
* 2. If the color of node is not equal to target-color, return.
|
||||
* 3. Add node to Q.
|
||||
* 4. For each element n of Q:
|
||||
* 5. If the color of n is equal to target-color:
|
||||
* 6. Set w and e equal to n.
|
||||
* 7. Move w to the west until the color of the node to the west of w no longer matches target-color.
|
||||
* 8. Move e to the east until the color of the node to the east of e no longer matches target-color.
|
||||
* 9. Set the color of nodes between w and e to replacement-color.
|
||||
* 10. For each node n between w and e:
|
||||
* 11. If the color of the node to the north of n is target-color, add that node to Q.
|
||||
* 12. If the color of the node to the south of n is target-color, add that node to Q.
|
||||
* 13. Continue looping until Q is exhausted.
|
||||
* 14. Return.
|
||||
*/
|
||||
var paintedPixels = [];
|
||||
var queue = [];
|
||||
var dy = [-1, 0, 1, 0];
|
||||
var dx = [0, 1, 0, -1];
|
||||
var targetColor;
|
||||
try {
|
||||
targetColor = frame.getPixel(col, row);
|
||||
} catch(e) {
|
||||
// Frame out of bound exception.
|
||||
}
|
||||
|
||||
if(targetColor == replacementColor) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
queue.push({"col": col, "row": row});
|
||||
var loopCount = 0;
|
||||
var cellCount = frame.getWidth() * frame.getHeight();
|
||||
while(queue.length > 0) {
|
||||
loopCount ++;
|
||||
|
||||
var currentItem = queue.pop();
|
||||
frame.setPixel(currentItem.col, currentItem.row, replacementColor);
|
||||
paintedPixels.push({"col": currentItem.col, "row": currentItem.row });
|
||||
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var nextCol = currentItem.col + dx[i];
|
||||
var nextRow = currentItem.row + dy[i];
|
||||
try {
|
||||
if (frame.containsPixel(nextCol, nextRow) && frame.getPixel(nextCol, nextRow) == targetColor) {
|
||||
queue.push({"col": nextCol, "row": nextRow });
|
||||
}
|
||||
|
||||
return pixels;
|
||||
},
|
||||
} catch(e) {
|
||||
// Frame out of bound exception.
|
||||
}
|
||||
}
|
||||
|
||||
getBoundRectanglePixels : function (x0, y0, x1, y1) {
|
||||
var rectangle = this.getOrderedRectangleCoordinates(x0, y0, x1, y1);
|
||||
var pixels = [];
|
||||
// Creating horizontal sides of the rectangle:
|
||||
for(var x = rectangle.x0; x <= rectangle.x1; x++) {
|
||||
pixels.push({"col": x, "row": rectangle.y0});
|
||||
pixels.push({"col": x, "row": rectangle.y1});
|
||||
}
|
||||
// Security loop breaker:
|
||||
if(loopCount > 10 * cellCount) {
|
||||
console.log("loop breaker called");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return paintedPixels;
|
||||
},
|
||||
|
||||
// Creating vertical sides of the rectangle:
|
||||
for(var y = rectangle.y0; y <= rectangle.y1; y++) {
|
||||
pixels.push({"col": rectangle.x0, "row": y});
|
||||
pixels.push({"col": rectangle.x1, "row": y});
|
||||
}
|
||||
|
||||
return pixels;
|
||||
},
|
||||
/**
|
||||
* Calculate and return the maximal DPI to display a picture in a given container.
|
||||
*
|
||||
* @param container jQueryObject Container where the picture should be displayed
|
||||
* @param number pictureHeight height in pixels of the picture to display
|
||||
* @param number pictureWidth width in pixels of the picture to display
|
||||
* @return number maximal dpi
|
||||
*/
|
||||
calculateDPIForContainer : function (container, pictureHeight, pictureWidth) {
|
||||
return this.calculateDPI(container.height(), container.width(), pictureHeight, pictureWidth);
|
||||
},
|
||||
|
||||
/**
|
||||
* Return an object of ordered rectangle coordinate.
|
||||
* In returned object {x0, y0} => top left corner - {x1, y1} => bottom right corner
|
||||
* @private
|
||||
*/
|
||||
getOrderedRectangleCoordinates : function (x0, y0, x1, y1) {
|
||||
return {
|
||||
x0 : Math.min(x0, x1), y0 : Math.min(y0, y1),
|
||||
x1 : Math.max(x0, x1), y1 : Math.max(y0, y1),
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Calculate and return the maximal DPI to display a picture for a given height and width.
|
||||
*
|
||||
* @param height number Height available to display the picture
|
||||
* @param width number Width available to display the picture
|
||||
* @param number pictureHeight height in pixels of the picture to display
|
||||
* @param number pictureWidth width in pixels of the picture to display
|
||||
* @return number maximal dpi
|
||||
*/
|
||||
calculateDPI : function (height, width, pictureHeight, pictureWidth) {
|
||||
var heightBoundDpi = Math.floor(height / pictureHeight),
|
||||
widthBoundDpi = Math.floor(width / pictureWidth);
|
||||
|
||||
/**
|
||||
* Return the list of pixels that would have been filled by a paintbucket tool applied
|
||||
* on pixel at coordinate (x,y).
|
||||
* This function is not altering the Frame object argument.
|
||||
*
|
||||
* @param frame pskl.model.Frame The frame target in which we want to paintbucket
|
||||
* @param col number Column coordinate in the frame
|
||||
* @param row number Row coordinate in the frame
|
||||
*
|
||||
* @return an array of the pixel coordinates paint with the replacement color
|
||||
*/
|
||||
getSimilarConnectedPixelsFromFrame: function(frame, col, row) {
|
||||
// To get the list of connected (eg the same color) pixels, we will use the paintbucket algorithm
|
||||
// in a fake cloned frame. The returned pixels by the paintbucket algo are the painted pixels
|
||||
// and are as well connected.
|
||||
var fakeFrame = frame.clone(); // We just want to
|
||||
var fakeFillColor = "sdfsdfsdf"; // A fake color that will never match a real color.
|
||||
var paintedPixels = this.paintSimilarConnectedPixelsFromFrame(fakeFrame, col, row, fakeFillColor);
|
||||
|
||||
return paintedPixels;
|
||||
},
|
||||
|
||||
/**
|
||||
* Apply the paintbucket tool in a frame at the (col, row) initial position
|
||||
* with the replacement color.
|
||||
*
|
||||
* @param frame pskl.model.Frame The frame target in which we want to paintbucket
|
||||
* @param col number Column coordinate in the frame
|
||||
* @param row number Row coordinate in the frame
|
||||
* @param replacementColor string Hexadecimal color used to fill the area
|
||||
*
|
||||
* @return an array of the pixel coordinates paint with the replacement color
|
||||
*/
|
||||
paintSimilarConnectedPixelsFromFrame: function(frame, col, row, replacementColor) {
|
||||
/**
|
||||
* Queue linear Flood-fill (node, target-color, replacement-color):
|
||||
* 1. Set Q to the empty queue.
|
||||
* 2. If the color of node is not equal to target-color, return.
|
||||
* 3. Add node to Q.
|
||||
* 4. For each element n of Q:
|
||||
* 5. If the color of n is equal to target-color:
|
||||
* 6. Set w and e equal to n.
|
||||
* 7. Move w to the west until the color of the node to the west of w no longer matches target-color.
|
||||
* 8. Move e to the east until the color of the node to the east of e no longer matches target-color.
|
||||
* 9. Set the color of nodes between w and e to replacement-color.
|
||||
* 10. For each node n between w and e:
|
||||
* 11. If the color of the node to the north of n is target-color, add that node to Q.
|
||||
* 12. If the color of the node to the south of n is target-color, add that node to Q.
|
||||
* 13. Continue looping until Q is exhausted.
|
||||
* 14. Return.
|
||||
*/
|
||||
var paintedPixels = [];
|
||||
var queue = [];
|
||||
var dy = [-1, 0, 1, 0];
|
||||
var dx = [0, 1, 0, -1];
|
||||
var targetColor;
|
||||
try {
|
||||
targetColor = frame.getPixel(col, row);
|
||||
} catch(e) {
|
||||
// Frame out of bound exception.
|
||||
}
|
||||
|
||||
if(targetColor == replacementColor) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
queue.push({"col": col, "row": row});
|
||||
var loopCount = 0;
|
||||
var cellCount = frame.getWidth() * frame.getHeight();
|
||||
while(queue.length > 0) {
|
||||
loopCount ++;
|
||||
|
||||
var currentItem = queue.pop();
|
||||
frame.setPixel(currentItem.col, currentItem.row, replacementColor);
|
||||
paintedPixels.push({"col": currentItem.col, "row": currentItem.row });
|
||||
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var nextCol = currentItem.col + dx[i];
|
||||
var nextRow = currentItem.row + dy[i];
|
||||
try {
|
||||
if (frame.containsPixel(nextCol, nextRow) && frame.getPixel(nextCol, nextRow) == targetColor) {
|
||||
queue.push({"col": nextCol, "row": nextRow });
|
||||
}
|
||||
} catch(e) {
|
||||
// Frame out of bound exception.
|
||||
}
|
||||
}
|
||||
|
||||
// Security loop breaker:
|
||||
if(loopCount > 10 * cellCount) {
|
||||
console.log("loop breaker called");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return paintedPixels;
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculate and return the maximal DPI to display a picture in a given container.
|
||||
*
|
||||
* @param container jQueryObject Container where the picture should be displayed
|
||||
* @param number pictureHeight height in pixels of the picture to display
|
||||
* @param number pictureWidth width in pixels of the picture to display
|
||||
* @return number maximal dpi
|
||||
*/
|
||||
calculateDPIForContainer : function (container, pictureHeight, pictureWidth) {
|
||||
return this.calculateDPI(container.height(), container.width(), pictureHeight, pictureWidth);
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculate and return the maximal DPI to display a picture for a given height and width.
|
||||
*
|
||||
* @param height number Height available to display the picture
|
||||
* @param width number Width available to display the picture
|
||||
* @param number pictureHeight height in pixels of the picture to display
|
||||
* @param number pictureWidth width in pixels of the picture to display
|
||||
* @return number maximal dpi
|
||||
*/
|
||||
calculateDPI : function (height, width, pictureHeight, pictureWidth) {
|
||||
var heightBoundDpi = Math.floor(height / pictureHeight),
|
||||
widthBoundDpi = Math.floor(width / pictureWidth);
|
||||
|
||||
return Math.min(heightBoundDpi, widthBoundDpi);
|
||||
},
|
||||
};
|
||||
return Math.min(heightBoundDpi, widthBoundDpi);
|
||||
},
|
||||
};
|
||||
})();
|
@ -1,76 +1,76 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl");
|
||||
var ns = $.namespace("pskl");
|
||||
|
||||
ns.UserSettings = {
|
||||
ns.UserSettings = {
|
||||
|
||||
SHOW_GRID : 'SHOW_GRID',
|
||||
CANVAS_BACKGROUND : 'CANVAS_BACKGROUND',
|
||||
SHOW_GRID : 'SHOW_GRID',
|
||||
CANVAS_BACKGROUND : 'CANVAS_BACKGROUND',
|
||||
|
||||
KEY_TO_DEFAULT_VALUE_MAP_ : {
|
||||
'SHOW_GRID' : false,
|
||||
'CANVAS_BACKGROUND' : 'medium-canvas-background'
|
||||
},
|
||||
KEY_TO_DEFAULT_VALUE_MAP_ : {
|
||||
'SHOW_GRID' : false,
|
||||
'CANVAS_BACKGROUND' : 'medium-canvas-background'
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
cache_ : {},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
cache_ : {},
|
||||
|
||||
/**
|
||||
* Static method to access a user defined settings value ot its default
|
||||
* value if not defined yet.
|
||||
*/
|
||||
get : function (key) {
|
||||
this.checkKeyValidity_(key);
|
||||
if (!(key in this.cache_)) {
|
||||
this.cache_[key] =
|
||||
this.readFromLocalStorage_(key) || this.readFromDefaults_(key);
|
||||
}
|
||||
return this.cache_[key];
|
||||
},
|
||||
/**
|
||||
* Static method to access a user defined settings value ot its default
|
||||
* value if not defined yet.
|
||||
*/
|
||||
get : function (key) {
|
||||
this.checkKeyValidity_(key);
|
||||
if (!(key in this.cache_)) {
|
||||
this.cache_[key] =
|
||||
this.readFromLocalStorage_(key) || this.readFromDefaults_(key);
|
||||
}
|
||||
return this.cache_[key];
|
||||
},
|
||||
|
||||
set : function (key, value) {
|
||||
this.checkKeyValidity_(key);
|
||||
this.cache_[key] = value;
|
||||
this.writeToLocalStorage_(key, value);
|
||||
set : function (key, value) {
|
||||
this.checkKeyValidity_(key);
|
||||
this.cache_[key] = value;
|
||||
this.writeToLocalStorage_(key, value);
|
||||
|
||||
$.publish(Events.USER_SETTINGS_CHANGED, [key, value]);
|
||||
},
|
||||
$.publish(Events.USER_SETTINGS_CHANGED, [key, value]);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
readFromLocalStorage_ : function(key) {
|
||||
var value = window.localStorage[key];
|
||||
if (typeof value != "undefined") {
|
||||
value = JSON.parse(value);
|
||||
}
|
||||
return value;
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
readFromLocalStorage_ : function(key) {
|
||||
var value = window.localStorage[key];
|
||||
if (typeof value != "undefined") {
|
||||
value = JSON.parse(value);
|
||||
}
|
||||
return value;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
writeToLocalStorage_ : function(key, value) {
|
||||
// TODO(grosbouddha): Catch storage exception here.
|
||||
window.localStorage[key] = JSON.stringify(value);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
writeToLocalStorage_ : function(key, value) {
|
||||
// TODO(grosbouddha): Catch storage exception here.
|
||||
window.localStorage[key] = JSON.stringify(value);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
readFromDefaults_ : function (key) {
|
||||
return this.KEY_TO_DEFAULT_VALUE_MAP_[key];
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
readFromDefaults_ : function (key) {
|
||||
return this.KEY_TO_DEFAULT_VALUE_MAP_[key];
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
checkKeyValidity_ : function(key) {
|
||||
if(!(key in this.KEY_TO_DEFAULT_VALUE_MAP_)) {
|
||||
// TODO(grosbouddha): Define error catching strategy and throw exception from here.
|
||||
console.log("UserSettings key <"+ key +"> not find in supported keys.");
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
checkKeyValidity_ : function(key) {
|
||||
if(!(key in this.KEY_TO_DEFAULT_VALUE_MAP_)) {
|
||||
// TODO(grosbouddha): Define error catching strategy and throw exception from here.
|
||||
console.log("UserSettings key <"+ key +"> not find in supported keys.");
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
@ -1,27 +1,27 @@
|
||||
jQuery.namespace = function() {
|
||||
var a=arguments, o=null, i, j, d;
|
||||
for (i=0; i<a.length; i=i+1) {
|
||||
d=a[i].split(".");
|
||||
o=window;
|
||||
for (j=0; j<d.length; j=j+1) {
|
||||
o[d[j]]=o[d[j]] || {};
|
||||
o=o[d[j]];
|
||||
}
|
||||
var a=arguments, o=null, i, j, d;
|
||||
for (i=0; i<a.length; i=i+1) {
|
||||
d=a[i].split(".");
|
||||
o=window;
|
||||
for (j=0; j<d.length; j=j+1) {
|
||||
o[d[j]]=o[d[j]] || {};
|
||||
o=o[d[j]];
|
||||
}
|
||||
return o;
|
||||
}
|
||||
return o;
|
||||
};
|
||||
|
||||
/**
|
||||
* Need a polyfill for PhantomJS
|
||||
*/
|
||||
if (typeof Function.prototype.bind !== "function") {
|
||||
Function.prototype.bind = function(scope) {
|
||||
"use strict";
|
||||
var _function = this;
|
||||
return function() {
|
||||
return _function.apply(scope, arguments);
|
||||
};
|
||||
Function.prototype.bind = function(scope) {
|
||||
"use strict";
|
||||
var _function = this;
|
||||
return function() {
|
||||
return _function.apply(scope, arguments);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
@ -31,19 +31,19 @@ if (typeof Function.prototype.bind !== "function") {
|
||||
*/
|
||||
(function() { // namespace: pskl.utils
|
||||
|
||||
var ns = $.namespace("pskl.utils");
|
||||
var ns = $.namespace("pskl.utils");
|
||||
|
||||
ns.rgbToHex = function(r, g, b) {
|
||||
if (r > 255 || g > 255 || b > 255)
|
||||
throw "Invalid color component";
|
||||
return ((r << 16) | (g << 8) | b).toString(16);
|
||||
};
|
||||
ns.rgbToHex = function(r, g, b) {
|
||||
if (r > 255 || g > 255 || b > 255)
|
||||
throw "Invalid color component";
|
||||
return ((r << 16) | (g << 8) | b).toString(16);
|
||||
};
|
||||
|
||||
ns.inherit = function(extendedObject, inheritFrom) {
|
||||
extendedObject.prototype = Object.create(inheritFrom.prototype);
|
||||
extendedObject.prototype.constructor = extendedObject;
|
||||
extendedObject.prototype.superclass = inheritFrom.prototype;
|
||||
};
|
||||
ns.inherit = function(extendedObject, inheritFrom) {
|
||||
extendedObject.prototype = Object.create(inheritFrom.prototype);
|
||||
extendedObject.prototype.constructor = extendedObject;
|
||||
extendedObject.prototype.superclass = inheritFrom.prototype;
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
|
@ -16,7 +16,8 @@
|
||||
"grunt-contrib-connect": "0.3.0",
|
||||
"grunt-contrib-jshint": "0.5.4",
|
||||
"grunt-contrib-uglify": "0.2.2",
|
||||
"grunt-contrib-concat": "0.1.2",
|
||||
"grunt-ghost": "1.0.12",
|
||||
"grunt-contrib-concat": "0.1.2"
|
||||
"grunt-leading-indent" : "0.1.0"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user