mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Merge pull request #482 from juliandescottes/feature-tiled-drawing
Feature tiled drawing
This commit is contained in:
commit
014a1d418f
@ -3,42 +3,37 @@
|
||||
/*******************************/
|
||||
|
||||
.background-picker-wrapper {
|
||||
display: inline-block;
|
||||
width: 130px;
|
||||
overflow: hidden;
|
||||
padding: 5px 5px 2px 5px;
|
||||
vertical-align: middle;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.background-picker {
|
||||
cursor: pointer;
|
||||
float: left;
|
||||
height: 35px;
|
||||
width: 35px;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
background-color: transparent;
|
||||
margin-right: 15px;
|
||||
margin-right: 5px;
|
||||
padding: 1px;
|
||||
position: relative;
|
||||
border: #888 2px solid;
|
||||
}
|
||||
|
||||
.background-picker:after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
right: -2px;
|
||||
bottom: -2px;
|
||||
left: -2px;
|
||||
.background-picker:hover {
|
||||
border-color: #eee;
|
||||
}
|
||||
|
||||
.background-picker:hover:after {
|
||||
border: #eee 1px solid;
|
||||
}
|
||||
|
||||
.background-picker.selected:after {
|
||||
border: gold 1px solid;
|
||||
.background-picker.selected {
|
||||
border-color: gold;
|
||||
}
|
||||
|
||||
.layer-opacity-input {
|
||||
margin: 5px;
|
||||
vertical-align: middle;
|
||||
width: 145px;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.layer-opacity-text {
|
||||
@ -53,9 +48,10 @@
|
||||
}
|
||||
|
||||
.grid-width-select {
|
||||
margin: 5px;
|
||||
margin: 5px 5px 0 5px;
|
||||
}
|
||||
|
||||
.settings-section-application > .settings-item > label {
|
||||
display: block;
|
||||
}
|
||||
.settings-section-application > .settings-title {
|
||||
/* Override the default 10px margin bottom for this panel */
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ var Constants = {
|
||||
|
||||
DEFAULT_PEN_COLOR : '#000000',
|
||||
TRANSPARENT_COLOR : 'rgba(0, 0, 0, 0)',
|
||||
SEAMLESS_MODE_OVERLAY_COLOR : 'rgba(255, 255, 255, 0.5)',
|
||||
|
||||
CURRENT_COLORS_PALETTE_ID : '__current-colors',
|
||||
|
||||
|
@ -116,8 +116,8 @@
|
||||
|
||||
ns.PreviewController.prototype.updateZoom_ = function () {
|
||||
var originalSizeEnabled = pskl.UserSettings.get(pskl.UserSettings.ORIGINAL_SIZE_PREVIEW);
|
||||
var tiledPreviewEnabled = pskl.UserSettings.get(pskl.UserSettings.TILED_PREVIEW);
|
||||
var useOriginalSize = originalSizeEnabled || tiledPreviewEnabled;
|
||||
var seamlessModeEnabled = pskl.UserSettings.get(pskl.UserSettings.SEAMLESS_MODE);
|
||||
var useOriginalSize = originalSizeEnabled || seamlessModeEnabled;
|
||||
|
||||
var zoom = useOriginalSize ? 1 : this.calculateZoom_();
|
||||
this.renderer.setZoom(zoom);
|
||||
@ -208,12 +208,12 @@
|
||||
};
|
||||
|
||||
ns.PreviewController.prototype.updateContainerDimensions_ = function () {
|
||||
var isTiled = pskl.UserSettings.get(pskl.UserSettings.TILED_PREVIEW);
|
||||
this.renderer.setRepeated(isTiled);
|
||||
var isSeamless = pskl.UserSettings.get(pskl.UserSettings.SEAMLESS_MODE);
|
||||
this.renderer.setRepeated(isSeamless);
|
||||
|
||||
var height, width;
|
||||
|
||||
if (isTiled) {
|
||||
if (isSeamless) {
|
||||
height = PREVIEW_SIZE;
|
||||
width = PREVIEW_SIZE;
|
||||
} else {
|
||||
|
@ -26,13 +26,13 @@
|
||||
|
||||
this.addEventListener(gridSelect, 'change', this.onGridWidthChange_);
|
||||
|
||||
// Tiled preview
|
||||
var tiledPreview = pskl.UserSettings.get(pskl.UserSettings.TILED_PREVIEW);
|
||||
var tiledPreviewCheckbox = document.querySelector('.tiled-preview-checkbox');
|
||||
if (tiledPreview) {
|
||||
tiledPreviewCheckbox.setAttribute('checked', tiledPreview);
|
||||
// Seamless mode
|
||||
var seamlessMode = pskl.UserSettings.get(pskl.UserSettings.SEAMLESS_MODE);
|
||||
var seamlessModeCheckbox = document.querySelector('.seamless-mode-checkbox');
|
||||
if (seamlessMode) {
|
||||
seamlessModeCheckbox.setAttribute('checked', seamlessMode);
|
||||
}
|
||||
this.addEventListener(tiledPreviewCheckbox, 'change', this.onTiledPreviewChange_);
|
||||
this.addEventListener(seamlessModeCheckbox, 'change', this.onSeamlessModeChange_);
|
||||
|
||||
// Max FPS
|
||||
var maxFpsInput = document.querySelector('.max-fps-input');
|
||||
@ -55,8 +55,8 @@
|
||||
pskl.UserSettings.set(pskl.UserSettings.GRID_WIDTH, width);
|
||||
};
|
||||
|
||||
ns.ApplicationSettingsController.prototype.onTiledPreviewChange_ = function (evt) {
|
||||
pskl.UserSettings.set(pskl.UserSettings.TILED_PREVIEW, evt.currentTarget.checked);
|
||||
ns.ApplicationSettingsController.prototype.onSeamlessModeChange_ = function (evt) {
|
||||
pskl.UserSettings.set(pskl.UserSettings.SEAMLESS_MODE, evt.currentTarget.checked);
|
||||
};
|
||||
|
||||
ns.ApplicationSettingsController.prototype.onBackgroundClick_ = function (evt) {
|
||||
|
@ -34,6 +34,7 @@
|
||||
var serializedFrame = [
|
||||
this.getZoom(),
|
||||
this.getGridWidth(),
|
||||
pskl.UserSettings.get('SEAMLESS_MODE'),
|
||||
offset.x, offset.y,
|
||||
size.width, size.height,
|
||||
frame.getHash()
|
||||
|
@ -237,6 +237,10 @@
|
||||
this.canvas = pskl.utils.CanvasUtils.createCanvas(frame.getWidth(), frame.getHeight());
|
||||
}
|
||||
|
||||
var w = this.canvas.width;
|
||||
var h = this.canvas.height;
|
||||
var z = this.zoom;
|
||||
|
||||
// Draw in canvas
|
||||
pskl.utils.FrameUtils.drawToCanvas(frame, this.canvas);
|
||||
|
||||
@ -245,31 +249,51 @@
|
||||
var displayContext = this.displayCanvas.getContext('2d');
|
||||
displayContext.save();
|
||||
|
||||
var smallerHeight = this.canvas.height * this.zoom < this.displayCanvas.height;
|
||||
var smallerWidth = this.canvas.width * this.zoom < this.displayCanvas.width;
|
||||
if (smallerHeight || smallerWidth) {
|
||||
displayContext.fillStyle = Constants.ZOOMED_OUT_BACKGROUND_COLOR;
|
||||
displayContext.fillRect(0, 0, this.displayCanvas.width - 1, this.displayCanvas.height - 1);
|
||||
}
|
||||
// Draw background
|
||||
displayContext.fillStyle = Constants.ZOOMED_OUT_BACKGROUND_COLOR;
|
||||
displayContext.fillRect(0, 0, this.displayCanvas.width - 1, this.displayCanvas.height - 1);
|
||||
|
||||
displayContext.translate(
|
||||
this.margin.x - this.offset.x * this.zoom,
|
||||
this.margin.y - this.offset.y * this.zoom
|
||||
this.margin.x - this.offset.x * z,
|
||||
this.margin.y - this.offset.y * z
|
||||
);
|
||||
|
||||
displayContext.clearRect(0, 0, this.canvas.width * this.zoom, this.canvas.height * this.zoom);
|
||||
|
||||
var isIE10 = pskl.utils.UserAgent.isIE && pskl.utils.UserAgent.version === 10;
|
||||
if (pskl.UserSettings.get('SEAMLESS_MODE')) {
|
||||
displayContext.clearRect(-1 * w * z, -1 * h * z, 3 * w * z, 3 * h * z);
|
||||
} else {
|
||||
displayContext.clearRect(0, 0, w * z, h * z);
|
||||
}
|
||||
|
||||
var gridWidth = this.computeGridWidthForDisplay_();
|
||||
var isGridEnabled = gridWidth > 0;
|
||||
if (isGridEnabled || isIE10) {
|
||||
var scaled = pskl.utils.ImageResizer.resizeNearestNeighbour(this.canvas, this.zoom, gridWidth);
|
||||
if (gridWidth > 0) {
|
||||
var scaled = pskl.utils.ImageResizer.resizeNearestNeighbour(this.canvas, z, gridWidth);
|
||||
|
||||
if (pskl.UserSettings.get('SEAMLESS_MODE')) {
|
||||
this.drawTiledFrames_(displayContext, scaled, w, h, z);
|
||||
}
|
||||
displayContext.drawImage(scaled, 0, 0);
|
||||
} else {
|
||||
displayContext.scale(this.zoom, this.zoom);
|
||||
displayContext.scale(z, z);
|
||||
|
||||
if (pskl.UserSettings.get('SEAMLESS_MODE')) {
|
||||
this.drawTiledFrames_(displayContext, this.canvas, w, h, 1);
|
||||
}
|
||||
displayContext.drawImage(this.canvas, 0, 0);
|
||||
}
|
||||
|
||||
displayContext.restore();
|
||||
};
|
||||
|
||||
/**
|
||||
* Draw repeatedly the provided image around the main drawing area. Used for seamless
|
||||
* drawing mode, to easily create seamless textures. A colored overlay is applied to
|
||||
* differentiate those additional frames from the main frame.
|
||||
*/
|
||||
ns.FrameRenderer.prototype.drawTiledFrames_ = function (context, image, w, h, z) {
|
||||
context.fillStyle = Constants.SEAMLESS_MODE_OVERLAY_COLOR;
|
||||
[[0, -1], [0, 1], [-1, -1], [-1, 0], [-1, 1], [1, -1], [1, 0], [1, 1]].forEach(function (d) {
|
||||
context.drawImage(image, d[0] * w * z, d[1] * h * z);
|
||||
context.fillRect(d[0] * w * z, d[1] * h * z, w * z, h * z);
|
||||
});
|
||||
};
|
||||
})();
|
||||
|
@ -7,7 +7,7 @@
|
||||
DEFAULT_SIZE : 'DEFAULT_SIZE',
|
||||
CANVAS_BACKGROUND : 'CANVAS_BACKGROUND',
|
||||
SELECTED_PALETTE : 'SELECTED_PALETTE',
|
||||
TILED_PREVIEW : 'TILED_PREVIEW',
|
||||
SEAMLESS_MODE : 'SEAMLESS_MODE',
|
||||
ORIGINAL_SIZE_PREVIEW : 'ORIGINAL_SIZE_PREVIEW',
|
||||
ONION_SKIN : 'ONION_SKIN',
|
||||
LAYER_PREVIEW : 'LAYER_PREVIEW',
|
||||
@ -26,7 +26,7 @@
|
||||
},
|
||||
'CANVAS_BACKGROUND' : 'lowcont-dark-canvas-background',
|
||||
'SELECTED_PALETTE' : Constants.CURRENT_COLORS_PALETTE_ID,
|
||||
'TILED_PREVIEW' : false,
|
||||
'SEAMLESS_MODE' : false,
|
||||
'ORIGINAL_SIZE_PREVIEW' : false,
|
||||
'ONION_SKIN' : false,
|
||||
'LAYER_OPACITY' : 0.2,
|
||||
|
@ -4,6 +4,7 @@
|
||||
<div class="settings-title">
|
||||
General
|
||||
</div>
|
||||
|
||||
<div class="settings-item">
|
||||
<label>Background</label>
|
||||
<div class="background-picker-wrapper">
|
||||
@ -23,7 +24,7 @@
|
||||
</div>
|
||||
|
||||
<div class="settings-item">
|
||||
<label for="grid-width">Grid</label>
|
||||
<label for="grid-width">Pixel Grid</label>
|
||||
<select id="grid-width" class="grid-width-select">
|
||||
<option value="0">Disabled</option>
|
||||
<option value="1">1px</option>
|
||||
@ -34,31 +35,24 @@
|
||||
</div>
|
||||
|
||||
<div class="settings-item">
|
||||
<label for="tiled-preview">Layer Preview Opacity</label>
|
||||
<label>Layer Opacity</label>
|
||||
<input type="range" class="layer-opacity-input" name="layer-opacity" min="0" max="1" step="0.05"/>
|
||||
<span class="layer-opacity-text"></span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<div class="settings-title">
|
||||
Preview
|
||||
</div>
|
||||
|
||||
<div class="settings-item">
|
||||
<label>
|
||||
<input type="checkbox" value="1" class="tiled-preview-checkbox checkbox-fix" name="tiled-preview-checkbox"/>
|
||||
Repeated preview
|
||||
Seamless drawing mode
|
||||
<input type="checkbox" value="1" class="seamless-mode-checkbox" name="seamless-mode-checkbox"/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="settings-item">
|
||||
<label for="tiled-preview">Maximum FPS </label>
|
||||
<label>Maximum FPS</label>
|
||||
<input type="text" class="textfield textfield-small max-fps-input" autocomplete="off" name="max-fps"/>
|
||||
</div>
|
||||
|
||||
<input type="submit" class="button button-primary" value="Save" />
|
||||
<input type="submit" class="button button-primary" value="Apply settings" />
|
||||
</div>
|
||||
</form>
|
||||
</script>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script type="text/html" id="templates/settings/export.html">
|
||||
<div class="settings-section settings-section-export">
|
||||
<div class="settings-title">Export</div>
|
||||
<div class="settings-item export-scale" title="Scale the exported PNG spritesheet"
|
||||
<div class="settings-item export-scale" title="Scale the animation for export"
|
||||
rel="tooltip"
|
||||
data-placement="top">
|
||||
<label for="scale-input">Scale</label>
|
||||
|
Loading…
Reference in New Issue
Block a user