Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new color palette apply tool and a new "Current frame" color palette #909

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/css/toolbox-palettes-list.css
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@
}

.palettes-list-select {
width: 66.66667%;
width: 66%;
height: 100%;
padding: 0 5px 0 5px;

color: #aaa;
font-size : 0.75em;
Expand Down
2 changes: 2 additions & 0 deletions src/js/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ var Constants = {

CURRENT_COLORS_PALETTE_ID : '__current-colors',

CURRENT_FRAME_COLORS_PALETTE_ID : '__current-frame-colors',

/*
* Fake semi-transparent color used to highlight transparent
* strokes and rectangles:
Expand Down
6 changes: 6 additions & 0 deletions src/js/Events.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ var Events = {

CURRENT_COLORS_UPDATED : 'CURRENT_COLORS_UPDATED',

CURRENT_FRAME_CHANGED: 'CURRENT_FRAME_CHANGED',

CURRENT_LAYER_CHANGED: 'CURRENT_LAYER_CHANGED',

CURRENT_PALETTE_CHANGED: 'CURRENT_PALETTE_CHANGED',

PERFORMANCE_REPORT_CHANGED : 'PERFORMANCE_REPORT_CHANGED',

PISKEL_FILE_IMPORT_FAILED : 'PISKEL_FILE_IMPORT_FAILED',
Expand Down
1 change: 1 addition & 0 deletions src/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

this.paletteService = new pskl.service.palette.PaletteService();
this.paletteService.addDynamicPalette(new pskl.service.palette.CurrentColorsPalette());
this.paletteService.addDynamicPalette(new pskl.service.palette.CurrentFrameColorsPalette());

this.selectedColorsService = new pskl.service.SelectedColorsService();
this.selectedColorsService.init();
Expand Down
5 changes: 4 additions & 1 deletion src/js/controller/PalettesListController.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@

ns.PalettesListController.prototype.selectPalette = function (paletteId) {
pskl.UserSettings.set(pskl.UserSettings.SELECTED_PALETTE, paletteId);
$.publish(Events.CURRENT_PALETTE_CHANGED)
};

ns.PalettesListController.prototype.getSelectedPaletteColors_ = function () {
Expand Down Expand Up @@ -148,8 +149,10 @@
};

ns.PalettesListController.prototype.onCreatePaletteClick_ = function (evt) {
var paletteId = this.colorPaletteSelect_.value;
$.publish(Events.DIALOG_SHOW, {
dialogId : 'create-palette'
dialogId : 'create-palette',
initArgs : paletteId
});
};

Expand Down
1 change: 1 addition & 0 deletions src/js/controller/TransformationsController.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
new pskl.tools.transform.Clone(),
new pskl.tools.transform.Center(),
new pskl.tools.transform.Crop(),
new pskl.tools.transform.PaletteApply(),
];

this.toolIconBuilder = new pskl.tools.ToolIconBuilder();
Expand Down
14 changes: 11 additions & 3 deletions src/js/controller/dialogs/CreatePaletteController.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
this.colorsListWidget = new pskl.widgets.ColorsList(colorsListContainer);

var palette;
var isCurrentColorsPalette = paletteId == Constants.CURRENT_COLORS_PALETTE_ID;
var isCurrentColorsPalette = paletteId == Constants.CURRENT_COLORS_PALETTE_ID || paletteId == Constants.CURRENT_FRAME_COLORS_PALETTE_ID;
if (paletteId && !isCurrentColorsPalette) {
importFileButton.style.display = 'none';
this.setTitle('Edit Palette');
Expand All @@ -43,8 +43,11 @@
this.setTitle('Create Palette');

var uuid = pskl.utils.Uuid.generate();
if (isCurrentColorsPalette) {
palette = new pskl.model.Palette(uuid, 'Current colors clone', this.getCurrentColors_());
if (paletteId == Constants.CURRENT_COLORS_PALETTE_ID) {
palette = new pskl.model.Palette(uuid, 'File colors copy', this.getCurrentColors_());
} else if (paletteId == Constants.CURRENT_FRAME_COLORS_PALETTE_ID) {
var frameId = pskl.app.piskelController.getCurrentFrameIndex() + 1;
palette = new pskl.model.Palette(uuid, 'frame:' + frameId + ' colors copy', this.getCurrentFrameColors_());
} else {
palette = new pskl.model.Palette(uuid, 'New palette', []);
}
Expand All @@ -58,6 +61,11 @@
return palette.getColors();
};

ns.CreatePaletteController.prototype.getCurrentFrameColors_ = function () {
var palette = this.paletteService.getPaletteById(Constants.CURRENT_FRAME_COLORS_PALETTE_ID);
return palette.getColors();
};

ns.CreatePaletteController.prototype.setPalette_ = function (palette) {
this.palette = palette;
this.nameInput.value = pskl.utils.unescapeHtml(palette.name);
Expand Down
2 changes: 2 additions & 0 deletions src/js/controller/piskel/PiskelController.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@
ns.PiskelController.prototype.setCurrentFrameIndex = function (index) {
if (this.hasFrameAt(index)) {
this.currentFrameIndex = index;
$.publish(Events.CURRENT_FRAME_CHANGED);
} else {
window.console.error('Could not set current frame index to ' + index);
}
Expand All @@ -258,6 +259,7 @@
ns.PiskelController.prototype.setCurrentLayerIndex = function (index) {
if (this.hasLayerAt(index)) {
this.currentLayerIndex = index;
$.publish(Events.CURRENT_LAYER_CHANGED);
} else {
window.console.error('Could not set current layer index to ' + index);
}
Expand Down
11 changes: 7 additions & 4 deletions src/js/model/Frame.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
this.id = __idCounter++;
this.version = 0;
this.pixels = ns.Frame.createEmptyPixelGrid_(width, height);
this.colorPalette = [];
this.stateIndex = 0;
} else {
throw 'Bad arguments in pskl.model.Frame constructor : ' + width + ', ' + height;
Expand Down Expand Up @@ -106,14 +107,16 @@
return [this.id, this.version].join('-');
};

ns.Frame.prototype.setPixel = function (x, y, color) {
ns.Frame.prototype.setPixel = function (x, y, entryColor) {
if (this.containsPixel(x, y)) {
var index = y * this.width + x;
var p = this.pixels[index];
color = pskl.utils.colorToInt(color);

var color = pskl.utils.colorToInt(entryColor);
if (p !== color) {
this.pixels[index] = color || pskl.utils.colorToInt(Constants.TRANSPARENT_COLOR);
var applyColor = color || pskl.utils.colorToInt(Constants.TRANSPARENT_COLOR);
this.pixels[index] = applyColor;

this.version++;
}
}
Expand Down
46 changes: 46 additions & 0 deletions src/js/service/CurrentColorsService.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// cache of current colors by history state
this.cache = {};
this.currentColors = [];
this.currentFrameColors = [];

this.cachedFrameProcessor = new pskl.model.frame.AsyncCachedFrameProcessor();
this.cachedFrameProcessor.setFrameProcessor(this.getFrameColors_.bind(this));
Expand All @@ -21,12 +22,19 @@
ns.CurrentColorsService.prototype.init = function () {
$.subscribe(Events.HISTORY_STATE_SAVED, this.throttledUpdateCurrentColors_);
$.subscribe(Events.HISTORY_STATE_LOADED, this.loadColorsFromCache_.bind(this));
$.subscribe(Events.CURRENT_FRAME_CHANGED, this.updateCurrentColors_.bind(this));
$.subscribe(Events.CURRENT_LAYER_CHANGED, this.updateCurrentColors_.bind(this));
$.subscribe(Events.CURRENT_PALETTE_CHANGED, this.updateCurrentColors_.bind(this));
};

ns.CurrentColorsService.prototype.getCurrentColors = function () {
return this.currentColors;
};

ns.CurrentColorsService.prototype.getCurrentFrameColors = function () {
return this.currentFrameColors
};

ns.CurrentColorsService.prototype.setCurrentColors = function (colors) {
var historyIndex = pskl.app.historyService.currentIndex;
this.cache[historyIndex] = colors;
Expand All @@ -36,6 +44,43 @@
}
};

// Current frame colors are tracked and updated for any future pixel indexing operations
ns.CurrentColorsService.prototype.updateCurrentFrameColors = function (frame) {
var currentFrameIndex = pskl.app.piskelController.getCurrentFrameIndex();
var frame = pskl.app.piskelController.getCurrentLayer().getFrameAt(currentFrameIndex);

this.updateFrameColors(frame);
$.publish(Events.CURRENT_COLORS_UPDATED);
};

ns.CurrentColorsService.prototype.updateFrameColors = function (frame) {
frame.colorPalette = [];
frame.forEachPixel(function (color, col, row, frame) {
if (color === 0) return;
if (!frame.colorPalette.includes(color)) {
frame.colorPalette.push(color)
}
})

// this.currentFrameColors keeps them as hexes, for the palette
this.currentFrameColors = frame.colorPalette.map(function(intColor) {
return pskl.utils.intToHex(intColor)
})
}

ns.CurrentColorsService.prototype.applyCurrentPaletteToIndexedPixels = function (applicationPalette, frame, update) {
this.updateFrameColors(frame);
applicationPalette.forEach(function(color, index) {
frame.forEachPixel(function (oldColor, col, row, frame) {
if (oldColor === 0) return;
var newPixelIndex = frame.colorPalette.indexOf(oldColor)
if (newPixelIndex === index) {
frame.setPixel(col, row, color);
}
})
});
}

ns.CurrentColorsService.prototype.isCurrentColorsPaletteSelected_ = function () {
var paletteId = pskl.UserSettings.get(pskl.UserSettings.SELECTED_PALETTE);
var palette = this.paletteService.getPaletteById(paletteId);
Expand Down Expand Up @@ -97,6 +142,7 @@
return pskl.utils.intToHex(color);
});
this.setCurrentColors(hexColors);
this.updateCurrentFrameColors();
}.bind(this));
};

Expand Down
2 changes: 1 addition & 1 deletion src/js/service/palette/CurrentColorsPalette.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
var ns = $.namespace('pskl.service.palette');

ns.CurrentColorsPalette = function () {
this.name = 'Current colors';
this.name = '* Current File *';
this.id = Constants.CURRENT_COLORS_PALETTE_ID;
this.colorSorter = new pskl.service.color.ColorSorter();
};
Expand Down
15 changes: 15 additions & 0 deletions src/js/service/palette/CurrentFrameColorsPalette.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
(function () {
var ns = $.namespace('pskl.service.palette');

ns.CurrentFrameColorsPalette = function () {
this.name = '- Current Frame -';
this.id = Constants.CURRENT_FRAME_COLORS_PALETTE_ID;
this.colorSorter = new pskl.service.color.ColorSorter();
};

ns.CurrentFrameColorsPalette.prototype.getColors = function () {
var currentColors = pskl.app.currentColorsService.getCurrentFrameColors();
currentColors = currentColors.slice(0, Constants.MAX_PALETTE_COLORS);
return currentColors;
};
})();
36 changes: 36 additions & 0 deletions src/js/tools/transform/PaletteApply.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
(function () {
var ns = $.namespace('pskl.tools.transform');

ns.PaletteApply = function () {
this.toolId = 'tool-colorswap';
this.helpText = "Apply the currently selected palette's colors to a frame via their index numbers";
this.tooltipDescriptors = [
{key : 'ctrl', description : 'Apply to all layers'},
{key : 'shift', description : 'Apply to all frames'}
];
};

pskl.utils.inherit(ns.PaletteApply, ns.AbstractTransformTool);

ns.PaletteApply.prototype.applyToolOnFrame_ = function (frame, altKey) {

var allLayers = pskl.utils.UserAgent.isMac ? event.metaKey : event.ctrlKey;
var allFrames = event.shiftKey;

var currentPalette = pskl.app.palettesListController.getSelectedPaletteColors_();
this.swapColors_(currentPalette, allLayers, allFrames)

};

ns.PaletteApply.prototype.swapColors_ = function(newPalette, allLayers, allFrames) {
var currentFrameIndex = pskl.app.piskelController.getCurrentFrameIndex();
var layers = allLayers ? pskl.app.piskelController.getLayers() : [pskl.app.piskelController.getCurrentLayer()];
layers.forEach(function (layer) {
var frames = allFrames ? layer.getFrames() : [layer.getFrameAt(currentFrameIndex)];
frames.forEach(function (frame) {
pskl.app.currentColorsService.applyCurrentPaletteToIndexedPixels(newPalette, frame, true);
}.bind(this));
}.bind(this));
}

})();
3 changes: 1 addition & 2 deletions src/js/utils/PixelUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,7 @@
/**
* 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 frame pskl.model.Frame The target in which we want to paintbucket. We set color on this frame.
* @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
Expand Down
2 changes: 2 additions & 0 deletions src/piskel-script-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@
"js/service/HistoryService.js",
"js/service/color/ColorSorter.js",
"js/service/palette/CurrentColorsPalette.js",
"js/service/palette/CurrentFrameColorsPalette.js",
"js/service/palette/PaletteService.js",
"js/service/palette/PaletteGplWriter.js",
"js/service/palette/reader/AbstractPaletteFileReader.js",
Expand Down Expand Up @@ -242,6 +243,7 @@
"js/tools/transform/Crop.js",
"js/tools/transform/Flip.js",
"js/tools/transform/Rotate.js",
"js/tools/transform/PaletteApply.js",
"js/tools/transform/TransformUtils.js",

// Devtools
Expand Down