diff --git a/js/piskel.js b/js/piskel.js
index 3600c233..38a067da 100644
--- a/js/piskel.js
+++ b/js/piskel.js
@@ -3,7 +3,6 @@
// Constants:
TRANSPARENT_COLOR = 'tc',
- //TRANSPARENT_COLOR = 'pink',
DEFAULT_PEN_COLOR = '#000000',
// Configuration:
@@ -52,7 +51,6 @@
frameSheet = FrameSheetModel.getInstance(framePixelWidth, framePixelHeight);
frameSheet.addEmptyFrame();
this.setActiveFrame(0);
-
this.initPalette();
this.initDrawingArea();
this.initPreviewSlideshow();
@@ -157,7 +155,6 @@
body.setAttribute('onmouseup', 'piskel.onCanvasMouseup(event)');
drawingAreaContainer.setAttribute('onmousedown', 'piskel.onCanvasMousedown(event)');
drawingAreaContainer.setAttribute('onmousemove', 'piskel.onCanvasMousemove(event)');
-
this.drawFrameToCanvas(frameSheet.getFrameByIndex(this.getActiveFrameIndex()), drawingAreaCanvas, drawingCanvasDpi);
},
@@ -218,6 +215,7 @@
}
$("display-fps").innerHTML = animPreviewFPS + " fps";
animFPSTuner.value = animPreviewFPS;
+ $("fps-value").innerHTML = animPreviewFPS + " fps";
refreshUpdater = startPreviewRefresh();
});
},
@@ -434,4 +432,5 @@
window.piskel = piskel;
piskel.init();
-})(function(id){return document.getElementById(id)});
\ No newline at end of file
+})(function(id){return document.getElementById(id)});
+//small change for checking my git setup :(
diff --git a/preview/css/piskel.css b/preview/css/piskel.css
new file mode 100644
index 00000000..c384327b
--- /dev/null
+++ b/preview/css/piskel.css
@@ -0,0 +1,36 @@
+html, body {
+ height : 100%;
+}
+
+.debug {
+ border : 1px Solid black;
+}
+
+.left-nav {
+ position:absolute;
+ top : 0;
+ bottom : 0;
+ width : 200px;
+ background : #000;
+}
+
+.main-panel {
+ position:absolute;
+ top : 0;
+ bottom : 0;
+ left : 200px;
+ right : 0;
+ background : #ccc;
+}
+
+.preview-container {
+ position : absolute;
+ top : 30px;
+ right : 0;
+ height : 200px;
+ width : 200px;
+ background : white;
+ border : 0px Solid black;
+ border-radius:5px 0px 0px 5px;
+ box-shadow : 0px 0px 2px rgba(0,0,0,0.2);
+}
\ No newline at end of file
diff --git a/preview/css/style.css b/preview/css/style.css
new file mode 100644
index 00000000..9136c5f0
--- /dev/null
+++ b/preview/css/style.css
@@ -0,0 +1,140 @@
+html, body {
+ height : 100%;
+ margin : 0;
+ cursor : default;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+ul, li {
+ margin : 0;
+ padding : 0;
+}
+
+.debug {
+ border : 1px Solid black;
+}
+
+.left-nav {
+ position:absolute;
+ top : 0;
+ bottom : 0;
+ width : 200px;
+ overflow-y: scroll;
+ background : #000;
+ padding : 10px;
+}
+
+.main-panel {
+ position:absolute;
+ top : 0;
+ bottom : 0;
+ left : 220px;
+ right : 0;
+ background : #ccc;
+}
+
+.preview-container {
+ position : absolute;
+ top : 30px;
+ right : 0;
+ height : 256px;
+ width : 256px;
+ background : white;
+ border : 0px Solid black;
+ border-radius:5px 0px 0px 5px;
+ box-shadow : 0px 0px 2px rgba(0,0,0,0.2);
+}
+
+.preview-container canvas {
+ border : 0px Solid transparent;
+ border-radius:5px 0px 0px 5px;
+}
+
+#cursorInfo {
+ position : fixed;
+ cursor : default;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.action-button {
+ background-color : white;
+ width : 150px;
+ display : inline-block;
+}
+
+#preview-list {
+ list-style-type: none;
+}
+
+.preview-tile {
+ padding : 10px;
+ overflow: hidden;
+ background-color: gray;
+}
+
+.preview-tile .canvas-container {
+ float: left;
+}
+
+.preview-tile .tile-view {
+ float: left;
+ border: blue 1px solid;
+}
+
+.preview-tile .tile-action {
+ display: none;
+ float: right;
+}
+
+.preview-tile:hover .tile-action {
+ display: block;
+}
+
+.preview-tile:hover {
+ background-color: lightgray;
+}
+
+#preview-list .preview-tile.selected {
+ background-color: lightyellow;
+}
+
+.canvas-container {
+ position: relative;
+ display: block;
+}
+
+.canvas-container .canvas-background {
+ background: url(../img/transparent_background.png) repeat;
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+}
+
+.canvas {
+ position: relative;
+ z-index: 1;
+}
+
+/* Force apparition of scrollbars on leopard */
+::-webkit-scrollbar {
+ -webkit-appearance: none;
+ width: 7px;
+}
+
+::-webkit-scrollbar-thumb {
+ border-radius: 4px;
+ background-color: rgba(180,180,180,.7);
+ -webkit-box-shadow: 0 0 1px rgba(255,255,255,.5);
+}
\ No newline at end of file
diff --git a/preview/img/transparent_background.png b/preview/img/transparent_background.png
new file mode 100644
index 00000000..4a1f7a8e
Binary files /dev/null and b/preview/img/transparent_background.png differ
diff --git a/preview/index.html b/preview/index.html
new file mode 100644
index 00000000..c08fa6e8
--- /dev/null
+++ b/preview/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+ Piskel
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/js/app.js b/preview/js/app.js
new file mode 100644
index 00000000..d66a847f
--- /dev/null
+++ b/preview/js/app.js
@@ -0,0 +1,35 @@
+// Generated by CoffeeScript 1.3.1
+(function() {
+
+ $(document).ready(function() {
+ var Piskel;
+ Piskel = Em.Application.create();
+ Piskel.mainView = Em.View.create({
+ templateName: 'main',
+ onCanvasClick: function() {}
+ });
+ Piskel.mainView.append;
+ Piskel.Art = Ember.Object.extend({
+ setContext: function(context) {
+ this.context = context;
+ },
+ clear: function() {
+ this.context.save();
+ return this.context.clearRect(0, 0, this.context.canvas.width, this.context.canvas.height);
+ }
+ });
+ $('#main').ready(function() {
+ var context, mainCanvas;
+ mainCanvas = document.getElementById('main');
+ context = mainCanvas.getContext('2d');
+ context.save();
+ context.clearRect(0, 0, context.canvas.width, context.canvas.height);
+ context.fillStyle = 'white';
+ context.fillRect(0, 0, context.canvas.width, context.canvas.height);
+ context.restore();
+ return Piskel.mainCanvas = document.getElementById('main');
+ });
+ return window.Piskel = Piskel;
+ });
+
+}).call(this);
diff --git a/preview/js/frameSheetModel.js b/preview/js/frameSheetModel.js
new file mode 100644
index 00000000..d4d2712b
--- /dev/null
+++ b/preview/js/frameSheetModel.js
@@ -0,0 +1,101 @@
+var FrameSheetModel = (function() {
+
+ var inst;
+ var frames = [];
+ var width;
+ var height;
+
+ var createEmptyFrame_ = function() {
+ var emptyFrame = new Array(width);
+ for (var columnIndex=0; columnIndex < width; columnIndex++) {
+ emptyFrame[columnIndex] = new Array(height);
+ }
+ return emptyFrame;
+ };
+
+ var serializeFrame_ = function (frame) {
+ var buffer = [];
+ for (var i = 0 ; i < frame.length ; i++) {
+ var serializedLine = "";
+ for(var j = 0 ; j < frame[i].length ; j++) {
+ if (typeof frame[i][j] == 'undefined' || frame[i][j] == 'tc') {
+ serializedLine += "0"
+ } else {
+ serializedLine += "1"
+ }
+ }
+ buffer.push(parseInt(serializedLine, 2).toString(36));
+
+ }
+ return buffer.join(",");
+ };
+
+ return {
+ validate: function() {
+ return true; // I'm always right dude
+ },
+
+ // Could be use to pass around model using long GET param (good enough for simple models) and
+ // do some temporary locastorage
+ serialize: function() {
+ var buffer = [];
+ for (var i = 0 ; i < frames.length ; i++) {
+ buffer.push(serializeFrame_(frames[i]));
+ }
+ return buffer.join("+");
+ //throw "FrameSheet.serialize Not implemented"
+ },
+
+ addEmptyFrame: function() {
+ this.addFrame(createEmptyFrame_());
+ },
+
+ addFrame : function (frame) {
+ frames.push(frame);
+ },
+
+ getFrameCount: function() {
+ return frames.length;
+ },
+
+ getFrameByIndex: function(index) {
+ if (isNaN(index)) {
+ throw "Bad argument value for getFrameByIndex method: <" + index + ">"
+ } else if (index < 0 || index > frames.length) {
+ throw "Out of bound index for frameSheet object."
+ }
+
+ return frames[index];
+ },
+
+ removeFrameByIndex: function(index) {
+ if(index < 0 || index > inst.getFrameCount()) {
+ throw "Bad index value for removeFrameByIndex.";
+ }
+ frames.splice(index, 1);
+ },
+
+ duplicateFrameByIndex: function(frameToDuplicateIndex) {
+ var frame = inst.getFrameByIndex(frameToDuplicateIndex);
+ var clonedFrame = [];
+ for(var i=0, l=frame.length; i 100) {
+ animPreviewFPS = 100;
+ }
+ animFPSTuner.value = animPreviewFPS;
+ refreshUpdater = startPreviewRefresh();
+ });
+ },
+
+ createPreviews : function () {
+ var container = $('preview-list'), previewTile;
+ container.innerHTML = "";
+ for (var i = 0, l = frameSheet.getFrameCount(); i < l ; i++) {
+ previewTile = this.createPreviewTile(i);
+ container.appendChild(previewTile);
+ }
+ },
+
+ createPreviewTile: function(tileNumber) {
+ var previewTileRoot = document.createElement("li");
+ var classname = "preview-tile";
+
+ if (this.getActiveFrameIndex() == tileNumber) {
+ classname += " selected";
+ }
+ previewTileRoot.className = classname;
+
+ var canvasContainer = document.createElement("div");
+ canvasContainer.className = "canvas-container";
+ canvasContainer.setAttribute('style',
+ 'width:' + framePixelWidth * previewTileCanvasDpi + 'px; height:' + framePixelHeight * previewTileCanvasDpi + 'px;');
+
+ var canvasBackground = document.createElement("div");
+ canvasBackground.className = "canvas-background";
+ canvasContainer.appendChild(canvasBackground);
+
+ var canvasPreview = document.createElement("canvas");
+ canvasPreview.className = "canvas tile-view"
+
+ canvasPreview.setAttribute('width', framePixelWidth * previewTileCanvasDpi);
+ canvasPreview.setAttribute('height', framePixelHeight * previewTileCanvasDpi);
+
+ previewTileRoot.addEventListener('click', function(evt) {
+ // has not class tile-action:
+ // TODO: let me know when you want to start using a framework :)
+ if(!evt.target.className.match(new RegExp('(\\s|^)'+ 'tile-action' +'(\\s|$)'))) {
+ piskel.setActiveFrameAndRedraw(tileNumber);
+ }
+ });
+
+ var canvasPreviewDuplicateAction = document.createElement("button");
+ canvasPreviewDuplicateAction.className = "tile-action"
+ canvasPreviewDuplicateAction.innerHTML = "dup"
+
+ canvasPreviewDuplicateAction.addEventListener('click', function(evt) {
+ piskel.duplicateFrame(tileNumber);
+ });
+
+ this.drawFrameToCanvas(frameSheet.getFrameByIndex(tileNumber), canvasPreview, previewTileCanvasDpi);
+ canvasContainer.appendChild(canvasPreview);
+ previewTileRoot.appendChild(canvasContainer);
+ previewTileRoot.appendChild(canvasPreviewDuplicateAction);
+
+ if(tileNumber > 0 || frameSheet.getFrameCount() > 1) {
+ var canvasPreviewDeleteAction = document.createElement("button");
+ canvasPreviewDeleteAction.className = "tile-action"
+ canvasPreviewDeleteAction.innerHTML = "del"
+ canvasPreviewDeleteAction.addEventListener('click', function(evt) {
+ frameSheet.removeFrameByIndex(tileNumber);
+ animIndex = 0;
+ piskel.createPreviews();
+ });
+ previewTileRoot.appendChild(canvasPreviewDeleteAction);
+ }
+
+ return previewTileRoot;
+ },
+
+ refreshAnimatedPreview : function () {
+ piskel.drawFrameToCanvas(frameSheet.getFrameByIndex(animIndex), previewCanvas, previewAnimationCanvasDpi);
+ animIndex++;
+ if (animIndex == frameSheet.getFrameCount()) {
+ animIndex = 0;
+ }
+ },
+
+ removeFrame: function(frameIndex) {
+ frameSheet.removeFrameByIndex(frameIndex);
+
+ this.setActiveFrameAndRedraw(frameIndex - 1);
+ },
+
+ duplicateFrame: function(frameIndex) {
+ frameSheet.duplicateFrameByIndex(frameIndex);
+
+ this.setActiveFrameAndRedraw(frameIndex + 1);
+ },
+
+ updateCursorInfo : function (event) {
+ var cursor = $('cursorInfo');
+ cursor.style.top = event.clientY + 10 + "px";
+ cursor.style.left = event.clientX + 10 + "px";
+
+ var coordinates = this.getRelativeCoordinates(event.clientX, event.clientY)
+ cursor.innerHTML = [
+ "X : " + coordinates.x,
+ "Y : " + coordinates.y
+ ].join(", ");
+ },
+
+ onCanvasMousedown : function (event) {
+ isClicked = true;
+ var coords = this.getRelativeCoordinates(event.clientX, event.clientY);
+ if(event.button == 0) {
+ this.drawAt(coords.x, coords.y, penColor);
+ } else {
+ // Right click used to delete.
+ isRightClicked = true;
+ this.drawAt(coords.x, coords.y, TRANSPARENT_COLOR);
+ }
+ },
+
+ onCanvasMousemove : function (event) {
+ //this.updateCursorInfo(event);
+ if (isClicked) {
+ var coords = this.getRelativeCoordinates(event.clientX, event.clientY);
+ if(isRightClicked) {
+ this.drawAt(coords.x, coords.y, TRANSPARENT_COLOR);
+ } else {
+ this.drawAt(coords.x, coords.y, penColor);
+ }
+ }
+ },
+
+ onCanvasMouseup : function (event) {
+ if(isClicked || 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.createPreviews();
+ }
+ isClicked = false;
+ isRightClicked = false;
+ },
+
+ drawAt : function (x, y, color) {
+ var pixelWidthIndex = (x - x%drawingCanvasDpi) / 10;
+ var pixelHeightIndex = (y - y%drawingCanvasDpi) / 10;
+
+ // Update model:
+ var currentFrame = frameSheet.getFrameByIndex(this.getActiveFrameIndex());
+
+ // TODO: make a better accessor for pixel state update:
+ // TODO: Make pen color dynamic:
+ currentFrame[pixelWidthIndex][pixelHeightIndex] = color;
+
+ // Update view:
+ // TODO: Create a per pixel update function for perf ?
+ this.drawFrameToCanvas(currentFrame, drawingAreaCanvas, drawingCanvasDpi);
+ },
+
+ // TODO: move that to a FrameRenderer (/w cache) ?
+ drawFrameToCanvas: function(frame, canvasElement, dpi) {
+ var pixelColor, context = canvasElement.getContext('2d');
+ for(var col = 0, num_col = frame.length; col < num_col; col++) {
+ for(var row = 0, num_row = frame[col].length; row < num_row; row++) {
+ pixelColor = frame[col][row];
+
+ if(pixelColor == undefined || pixelColor == TRANSPARENT_COLOR) {
+ context.clearRect(col * dpi, row * dpi, dpi, dpi);
+ } else {
+ context.fillStyle = pixelColor;
+ context.fillRect(col * dpi, row * dpi, dpi, dpi);
+ }
+
+
+ }
+ }
+ },
+
+ onCanvasContextMenu : function (event) {
+ event.preventDefault();
+ event.stopPropagation();
+ event.cancelBubble = true;
+ return false;
+ },
+
+ getRelativeCoordinates : function (x, y) {
+ var canvasRect = drawingAreaCanvas.getBoundingClientRect();
+ return {
+ x : x - canvasRect.left,
+ y : y - canvasRect.top
+ }
+ }
+ };
+
+ window.piskel = piskel;
+ piskel.init();
+
+})(function(id){return document.getElementById(id)});
\ No newline at end of file