mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Adding spritesheet import
- Updated the import dialog to allow users to specify the number of frames in the image (which defaults to 1 x and 1 y) - Setting the frame count for x and y will draw a dotted line in the preview that shows where the image will be split into individual frames - When imported with a frame count above 1, the source image will be split into the different frames and loaded just as if it were an animated gif - This allows users to import existing spritesheet pngs, including those produced by the piskel export function
This commit is contained in:
parent
8d85093874
commit
48f24c0cf3
@ -3,6 +3,7 @@
|
|||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
|
|
||||||
.import-section-preview {
|
.import-section-preview {
|
||||||
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
width: 60px;
|
width: 60px;
|
||||||
@ -10,9 +11,19 @@
|
|||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.import-section-preview.no-border {
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.import-section-preview canvas {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.dialog-section-title {
|
.dialog-section-title {
|
||||||
display : inline-block;
|
display : inline-block;
|
||||||
width: 55px;
|
width: 70px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.import-size-field:nth-of-type(2) {
|
.import-size-field:nth-of-type(2) {
|
||||||
|
@ -67,7 +67,7 @@
|
|||||||
|
|
||||||
#dialog-container.import-image {
|
#dialog-container.import-image {
|
||||||
width: 500px;
|
width: 500px;
|
||||||
height: 300px;
|
height: 320px;
|
||||||
top : 50%;
|
top : 50%;
|
||||||
left : 50%;
|
left : 50%;
|
||||||
position : absolute;
|
position : absolute;
|
||||||
|
@ -22,8 +22,13 @@
|
|||||||
this.resizeHeight = $('[name=resize-height]');
|
this.resizeHeight = $('[name=resize-height]');
|
||||||
this.smoothResize = $('[name=smooth-resize-checkbox]');
|
this.smoothResize = $('[name=smooth-resize-checkbox]');
|
||||||
|
|
||||||
|
this.frameCountX = $('[name=frame-count-x]');
|
||||||
|
this.frameCountY = $('[name=frame-count-y]');
|
||||||
|
|
||||||
this.resizeWidth.keyup(this.onResizeInputKeyUp_.bind(this, 'width'));
|
this.resizeWidth.keyup(this.onResizeInputKeyUp_.bind(this, 'width'));
|
||||||
this.resizeHeight.keyup(this.onResizeInputKeyUp_.bind(this, 'height'));
|
this.resizeHeight.keyup(this.onResizeInputKeyUp_.bind(this, 'height'));
|
||||||
|
this.frameCountX.keyup(this.onResizeInputKeyUp_.bind(this, 'frameCountX'));
|
||||||
|
this.frameCountY.keyup(this.onResizeInputKeyUp_.bind(this, 'frameCountY'));
|
||||||
|
|
||||||
this.importImageForm = $('[name=import-image-form]');
|
this.importImageForm = $('[name=import-image-form]');
|
||||||
this.importImageForm.submit(this.onImportFormSubmit_.bind(this));
|
this.importImageForm.submit(this.onImportFormSubmit_.bind(this));
|
||||||
@ -49,7 +54,24 @@
|
|||||||
}
|
}
|
||||||
var height = this.importedImage_.height;
|
var height = this.importedImage_.height;
|
||||||
var width = this.importedImage_.width;
|
var width = this.importedImage_.width;
|
||||||
if (from === 'width') {
|
|
||||||
|
var frameCountX = parseInt(this.frameCountX.val(), 10);
|
||||||
|
if (frameCountX <= 0 || isNaN(frameCountX)) {
|
||||||
|
this.frameCountX.val(1);
|
||||||
|
frameCountX = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var frameCountY = parseInt(this.frameCountY.val(), 10);
|
||||||
|
if (frameCountY <= 0 || isNaN(frameCountY)) {
|
||||||
|
this.frameCountY.val(1);
|
||||||
|
frameCountY = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from === 'frameCountX' || from === 'frameCountY') {
|
||||||
|
this.resizeWidth.val(Math.round(width / frameCountX));
|
||||||
|
this.resizeHeight.val(Math.round(height / frameCountY));
|
||||||
|
this.drawFramesGrid_();
|
||||||
|
} else if (from === 'width') {
|
||||||
this.resizeHeight.val(Math.round(value * height / width));
|
this.resizeHeight.val(Math.round(value * height / width));
|
||||||
} else {
|
} else {
|
||||||
this.resizeWidth.val(Math.round(value * width / height));
|
this.resizeWidth.val(Math.round(value * width / height));
|
||||||
@ -72,6 +94,9 @@
|
|||||||
this.resizeWidth.val(w);
|
this.resizeWidth.val(w);
|
||||||
this.resizeHeight.val(h);
|
this.resizeHeight.val(h);
|
||||||
|
|
||||||
|
this.frameCountX.val(1);
|
||||||
|
this.frameCountY.val(1);
|
||||||
|
|
||||||
this.importPreview.width('auto');
|
this.importPreview.width('auto');
|
||||||
this.importPreview.html('');
|
this.importPreview.html('');
|
||||||
this.importPreview.append(this.createImagePreview_());
|
this.importPreview.append(this.createImagePreview_());
|
||||||
@ -113,7 +138,11 @@
|
|||||||
this.closeDialog();
|
this.closeDialog();
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
error: function () {
|
error: function () {
|
||||||
this.createPiskelFromImages_([image]);
|
var images = pskl.utils.CanvasUtils.createFramesFromImage(
|
||||||
|
image,
|
||||||
|
this.frameCountX.val(),
|
||||||
|
this.frameCountY.val());
|
||||||
|
this.createPiskelFromImages_(images);
|
||||||
this.closeDialog();
|
this.closeDialog();
|
||||||
}.bind(this)
|
}.bind(this)
|
||||||
});
|
});
|
||||||
@ -143,4 +172,54 @@
|
|||||||
pskl.app.piskelController.setPiskel(piskel);
|
pskl.app.piskelController.setPiskel(piskel);
|
||||||
pskl.app.previewController.setFPS(Constants.DEFAULT.FPS);
|
pskl.app.previewController.setFPS(Constants.DEFAULT.FPS);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ns.ImportImageController.prototype.drawFramesGrid_ = function () {
|
||||||
|
var canvasWrapper = this.importPreview.children('canvas');
|
||||||
|
var countX = this.frameCountX.val();
|
||||||
|
var countY = this.frameCountY.val();
|
||||||
|
if (countX > 1 || countY > 1) {
|
||||||
|
var width = this.importedImage_.width;
|
||||||
|
var height = this.importedImage_.height;
|
||||||
|
var frameW = width / countX;
|
||||||
|
var frameH = height / countY;
|
||||||
|
|
||||||
|
var canvas = canvasWrapper.get(0);
|
||||||
|
if (!canvasWrapper.length) {
|
||||||
|
// Create a new canvas for the grid
|
||||||
|
canvas = pskl.utils.CanvasUtils.createCanvas(width + 1, height + 1);
|
||||||
|
this.importPreview.append(canvas);
|
||||||
|
canvasWrapper = $(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
var context = canvas.getContext('2d');
|
||||||
|
context.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
context.beginPath();
|
||||||
|
|
||||||
|
// Draw the vertical lines
|
||||||
|
for (var x = 0.5; x < width + 1; x += frameW) {
|
||||||
|
context.moveTo(x, 0);
|
||||||
|
context.lineTo(x, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the horizontal lines
|
||||||
|
for (var y = 0.5; y < height + 1; y += frameH) {
|
||||||
|
context.moveTo(0, y);
|
||||||
|
context.lineTo(width, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the line style to dashed
|
||||||
|
context.lineWidth = 1;
|
||||||
|
context.setLineDash([2, 1]);
|
||||||
|
context.strokeStyle = '#000000';
|
||||||
|
context.stroke();
|
||||||
|
|
||||||
|
// Resize the canvas so that it matches the preview height and stretches correctly
|
||||||
|
canvasWrapper.height(PREVIEW_HEIGHT + 1);
|
||||||
|
canvasWrapper.show();
|
||||||
|
this.importPreview.addClass('no-border');
|
||||||
|
} else {
|
||||||
|
canvasWrapper.hide();
|
||||||
|
this.importPreview.removeClass('no-border');
|
||||||
|
}
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
@ -33,6 +33,43 @@
|
|||||||
return canvas;
|
return canvas;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits the specified image into several new canvas elements based on the
|
||||||
|
* supplied horizontal (x) and vertical (y) counts.
|
||||||
|
* @param image The source image that will be split
|
||||||
|
* @param {Number} frameCountX The number of frames in the horizontal axis
|
||||||
|
* @param {Number} frameCountY The number of frames in the vertical axis
|
||||||
|
* @returns {Array} An array of canvas elements that contain the split frames
|
||||||
|
*/
|
||||||
|
createFramesFromImage : function (image, frameCountX, frameCountY) {
|
||||||
|
var canvasArray = [];
|
||||||
|
var frameWidth = image.width / frameCountX;
|
||||||
|
var frameHeight = image.height / frameCountY;
|
||||||
|
|
||||||
|
// Loop through the frames prioritizing the spritesheet as horizonal strips
|
||||||
|
for (var y = 0; y < frameCountY; y++) {
|
||||||
|
for (var x = 0; x < frameCountX; x++) {
|
||||||
|
var canvas = pskl.utils.CanvasUtils.createCanvas(frameWidth, frameHeight);
|
||||||
|
var context = canvas.getContext('2d');
|
||||||
|
|
||||||
|
// Blit the correct part of the source image into the new canvas
|
||||||
|
context.drawImage(
|
||||||
|
image,
|
||||||
|
x * frameWidth,
|
||||||
|
y * frameHeight,
|
||||||
|
frameWidth,
|
||||||
|
image.height,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
frameWidth,
|
||||||
|
image.height);
|
||||||
|
|
||||||
|
canvasArray.push(canvas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return canvasArray;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* By default, all scaling operations on a Canvas 2D Context are performed using antialiasing.
|
* By default, all scaling operations on a Canvas 2D Context are performed using antialiasing.
|
||||||
* Resizing a 32x32 image to 320x320 will lead to a blurry output.
|
* Resizing a 32x32 image to 320x320 will lead to a blurry output.
|
||||||
|
@ -17,6 +17,11 @@
|
|||||||
<input type="text" class="textfield import-size-field" name="resize-width" />x
|
<input type="text" class="textfield import-size-field" name="resize-width" />x
|
||||||
<input type="text" class="textfield import-size-field" name="resize-height" />
|
<input type="text" class="textfield import-size-field" name="resize-height" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="import-section">
|
||||||
|
<span class="dialog-section-title">Frames :</span>
|
||||||
|
<input type="text" class="textfield import-size-field" name="frame-count-x" />x
|
||||||
|
<input type="text" class="textfield import-size-field" name="frame-count-y" />
|
||||||
|
</div>
|
||||||
<div class="import-section">
|
<div class="import-section">
|
||||||
<span class="import-section-title">Smooth resize :</span>
|
<span class="import-section-title">Smooth resize :</span>
|
||||||
<input type="checkbox" checked="checked" name="smooth-resize-checkbox" value="1" />
|
<input type="checkbox" checked="checked" name="smooth-resize-checkbox" value="1" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user