mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-29 19:20:09 +00:00
[lua] Add app.range.colors + Move/CopyColors commands
Closes: https://community.aseprite.org/t/2512
This commit is contained in:
parent
1995d67759
commit
35aaa18ee3
@ -249,6 +249,7 @@ Outline = Outline
|
||||
ConvolutionMatrix = Convolution Matrix
|
||||
Copy = Copy
|
||||
CopyCel = Copy Cel
|
||||
CopyColors = Copy Colors
|
||||
CopyMerged = Copy Merged
|
||||
CropSprite = Crop Sprite
|
||||
Cut = Cut
|
||||
@ -327,6 +328,7 @@ Move_Right = right
|
||||
Move_Up = up
|
||||
Move_Down = down
|
||||
MoveCel = Move Cel
|
||||
MoveColors = Move Colors
|
||||
MoveMask = Move {0} {1}
|
||||
MoveMask_Boundaries = Selection Boundaries
|
||||
MoveMask_Content = Selection Content
|
||||
|
@ -523,6 +523,7 @@ add_library(app-lib
|
||||
commands/filters/convolution_matrix_stock.cpp
|
||||
commands/filters/filter_manager_impl.cpp
|
||||
commands/filters/filter_worker.cpp
|
||||
commands/move_colors_command.cpp
|
||||
commands/move_thing.cpp
|
||||
commands/new_params.cpp
|
||||
commands/quick_command.cpp
|
||||
@ -596,6 +597,7 @@ add_library(app-lib
|
||||
util/layer_boundaries.cpp
|
||||
util/msk_file.cpp
|
||||
util/new_image_from_mask.cpp
|
||||
util/pal_ops.cpp
|
||||
util/pic_file.cpp
|
||||
util/pixel_ratio.cpp
|
||||
util/range_utils.cpp
|
||||
|
@ -64,6 +64,7 @@ void ActiveSiteHandler::getActiveSiteForDoc(Doc* doc, Site* site)
|
||||
site->sprite(doc->sprite());
|
||||
site->layer(doc::get<doc::Layer>(data.layer));
|
||||
site->frame(data.frame);
|
||||
site->selectedColors(data.selectedColors);
|
||||
}
|
||||
|
||||
void ActiveSiteHandler::setActiveLayerInDoc(Doc* doc, doc::Layer* layer)
|
||||
@ -78,6 +79,12 @@ void ActiveSiteHandler::setActiveFrameInDoc(Doc* doc, doc::frame_t frame)
|
||||
data.frame = frame;
|
||||
}
|
||||
|
||||
void ActiveSiteHandler::setSelectedColorsInDoc(Doc* doc, const doc::PalettePicks& picks)
|
||||
{
|
||||
Data& data = getData(doc);
|
||||
data.selectedColors = picks;
|
||||
}
|
||||
|
||||
void ActiveSiteHandler::onAddLayer(DocEvent& ev)
|
||||
{
|
||||
Data& data = getData(ev.document());
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "app/doc_observer.h"
|
||||
#include "doc/frame.h"
|
||||
#include "doc/object_id.h"
|
||||
#include "doc/palette_picks.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
@ -37,6 +38,7 @@ namespace app {
|
||||
void getActiveSiteForDoc(Doc* doc, Site* site);
|
||||
void setActiveLayerInDoc(Doc* doc, doc::Layer* layer);
|
||||
void setActiveFrameInDoc(Doc* doc, doc::frame_t frame);
|
||||
void setSelectedColorsInDoc(Doc* doc, const doc::PalettePicks& picks);
|
||||
|
||||
private:
|
||||
// DocObserver impl
|
||||
@ -49,6 +51,7 @@ namespace app {
|
||||
struct Data {
|
||||
doc::ObjectId layer;
|
||||
doc::frame_t frame;
|
||||
doc::PalettePicks selectedColors;
|
||||
};
|
||||
|
||||
Data& getData(Doc* doc);
|
||||
|
@ -13,6 +13,7 @@ FOR_EACH_COMMAND(CelOpacity)
|
||||
FOR_EACH_COMMAND(ChangePixelFormat)
|
||||
FOR_EACH_COMMAND(ColorCurve)
|
||||
FOR_EACH_COMMAND(ConvolutionMatrix)
|
||||
FOR_EACH_COMMAND(CopyColors)
|
||||
FOR_EACH_COMMAND(CropSprite)
|
||||
FOR_EACH_COMMAND(Despeckle)
|
||||
FOR_EACH_COMMAND(ExportSpriteSheet)
|
||||
@ -22,6 +23,7 @@ FOR_EACH_COMMAND(InvertColor)
|
||||
FOR_EACH_COMMAND(LayerFromBackground)
|
||||
FOR_EACH_COMMAND(LoadPalette)
|
||||
FOR_EACH_COMMAND(MergeDownLayer)
|
||||
FOR_EACH_COMMAND(MoveColors)
|
||||
FOR_EACH_COMMAND(NewFile)
|
||||
FOR_EACH_COMMAND(NewFrame)
|
||||
FOR_EACH_COMMAND(NewLayer)
|
||||
|
@ -189,6 +189,10 @@ bool FilterManagerImpl::applyStep()
|
||||
m_maskIterator = m_maskBits.begin();
|
||||
}
|
||||
|
||||
if (m_row == 0) {
|
||||
applyToPaletteIfNeeded();
|
||||
}
|
||||
|
||||
switch (m_site.sprite()->pixelFormat()) {
|
||||
case IMAGE_RGB: m_filter->applyToRgba(this); break;
|
||||
case IMAGE_GRAYSCALE: m_filter->applyToGrayscale(this); break;
|
||||
@ -240,6 +244,8 @@ void FilterManagerImpl::apply()
|
||||
|
||||
void FilterManagerImpl::applyToTarget()
|
||||
{
|
||||
applyToPaletteIfNeeded();
|
||||
|
||||
const bool paletteChange = paletteHasChanged();
|
||||
bool cancelled = false;
|
||||
|
||||
@ -441,15 +447,7 @@ Palette* FilterManagerImpl::getNewPalette()
|
||||
|
||||
doc::PalettePicks FilterManagerImpl::getPalettePicks()
|
||||
{
|
||||
doc::PalettePicks picks;
|
||||
#ifdef ENABLE_UI // TODO add palette entries in Site and use activeSite here
|
||||
if (auto colorBar = ColorBar::instance()) {
|
||||
colorBar
|
||||
->getPaletteView()
|
||||
->getSelectedEntries(picks);
|
||||
}
|
||||
#endif
|
||||
return picks;
|
||||
return m_site.selectedColors();
|
||||
}
|
||||
|
||||
void FilterManagerImpl::init(Cel* cel)
|
||||
@ -512,6 +510,11 @@ void FilterManagerImpl::restoreSpritePalette()
|
||||
m_site.sprite()->setPalette(m_oldPalette.get(), false);
|
||||
}
|
||||
|
||||
void FilterManagerImpl::applyToPaletteIfNeeded()
|
||||
{
|
||||
m_filter->applyToPalette(this);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_UI
|
||||
|
||||
void FilterManagerImpl::redrawColorPalette()
|
||||
|
@ -78,8 +78,6 @@ namespace app {
|
||||
|
||||
void setProgressDelegate(IProgressDelegate* progressDelegate);
|
||||
|
||||
doc::PixelFormat pixelFormat() const;
|
||||
|
||||
void setTarget(Target target);
|
||||
void setCelsTarget(CelsTarget celsTarget);
|
||||
|
||||
@ -109,6 +107,7 @@ namespace app {
|
||||
#endif
|
||||
|
||||
// FilterManager implementation
|
||||
doc::PixelFormat pixelFormat() const override;
|
||||
const void* getSourceAddress() override;
|
||||
void* getDestinationAddress() override;
|
||||
int getWidth() override { return m_bounds.w; }
|
||||
@ -137,6 +136,7 @@ namespace app {
|
||||
// modifies the palette).
|
||||
bool paletteHasChanged();
|
||||
void restoreSpritePalette();
|
||||
void applyToPaletteIfNeeded();
|
||||
|
||||
#ifdef ENABLE_UI
|
||||
void redrawColorPalette();
|
||||
|
107
src/app/commands/move_colors_command.cpp
Normal file
107
src/app/commands/move_colors_command.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/commands/cmd_set_palette.h"
|
||||
#include "app/commands/new_params.h"
|
||||
#include "app/context.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/doc_api.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/tx.h"
|
||||
#include "app/util/pal_ops.h"
|
||||
#include "doc/palette.h"
|
||||
#include "doc/palette_picks.h"
|
||||
#include "doc/remap.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
using namespace ui;
|
||||
|
||||
struct MoveColorsParams : public NewParams {
|
||||
Param<int> before { this, 0, "before" };
|
||||
};
|
||||
|
||||
class MoveColorsCommand : public CommandWithNewParams<MoveColorsParams> {
|
||||
public:
|
||||
MoveColorsCommand(bool copy)
|
||||
: CommandWithNewParams<MoveColorsParams>(
|
||||
(copy ? CommandId::CopyColors():
|
||||
CommandId::MoveColors()), CmdRecordableFlag),
|
||||
m_copy(copy) { }
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* ctx) override {
|
||||
return ctx->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::HasSelectedColors);
|
||||
}
|
||||
|
||||
void onExecute(Context* ctx) override {
|
||||
ContextWriter writer(ctx);
|
||||
Site site = ctx->activeSite();
|
||||
|
||||
PalettePicks picks = site.selectedColors();
|
||||
if (picks.picks() == 0)
|
||||
return; // Do nothing
|
||||
|
||||
ASSERT(writer.palette());
|
||||
if (!writer.palette())
|
||||
return;
|
||||
|
||||
Tx tx(writer.context(), friendlyName(), ModifyDocument);
|
||||
const int beforeIndex = params().before();
|
||||
int currentEntry = picks.firstPick();
|
||||
|
||||
#ifdef ENABLE_UI
|
||||
if (ctx->isUIAvailable()) {
|
||||
auto& fgColor = Preferences::instance().colorBar.fgColor;
|
||||
if (fgColor().getType() == app::Color::IndexType)
|
||||
currentEntry = fgColor().getIndex();
|
||||
}
|
||||
#endif
|
||||
|
||||
doc::Palette palette(*writer.palette());
|
||||
doc::Palette newPalette(palette);
|
||||
move_or_copy_palette_colors(palette, newPalette, picks,
|
||||
currentEntry,
|
||||
beforeIndex,
|
||||
m_copy);
|
||||
|
||||
writer.document()->getApi(tx)
|
||||
.setPalette(writer.sprite(), writer.frame(), &newPalette);
|
||||
|
||||
ctx->setSelectedColors(picks);
|
||||
|
||||
#ifdef ENABLE_UI
|
||||
if (ctx->isUIAvailable()) {
|
||||
auto& fgColor = Preferences::instance().colorBar.fgColor;
|
||||
if (fgColor().getType() == app::Color::IndexType)
|
||||
fgColor(Color::fromIndex(currentEntry));
|
||||
}
|
||||
#endif
|
||||
|
||||
tx.commit();
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_copy;
|
||||
};
|
||||
|
||||
Command* CommandFactory::createMoveColorsCommand()
|
||||
{
|
||||
return new MoveColorsCommand(false);
|
||||
}
|
||||
|
||||
Command* CommandFactory::createCopyColorsCommand()
|
||||
{
|
||||
return new MoveColorsCommand(true);
|
||||
}
|
||||
|
||||
} // namespace app
|
@ -81,6 +81,11 @@ void Context::setActiveFrame(const doc::frame_t frame)
|
||||
onSetActiveFrame(frame);
|
||||
}
|
||||
|
||||
void Context::setSelectedColors(const doc::PalettePicks& picks)
|
||||
{
|
||||
onSetSelectedColors(picks);
|
||||
}
|
||||
|
||||
bool Context::hasModifiedDocuments() const
|
||||
{
|
||||
for (auto doc : documents())
|
||||
@ -217,6 +222,12 @@ void Context::onSetActiveFrame(const doc::frame_t frame)
|
||||
activeSiteHandler()->setActiveFrameInDoc(m_lastSelectedDoc, frame);
|
||||
}
|
||||
|
||||
void Context::onSetSelectedColors(const doc::PalettePicks& picks)
|
||||
{
|
||||
if (m_lastSelectedDoc)
|
||||
activeSiteHandler()->setSelectedColorsInDoc(m_lastSelectedDoc, picks);
|
||||
}
|
||||
|
||||
void Context::setTransaction(Transaction* transaction)
|
||||
{
|
||||
if (transaction) {
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
namespace doc {
|
||||
class Layer;
|
||||
class PalettePicks;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
@ -85,6 +86,7 @@ namespace app {
|
||||
void setActiveDocument(Doc* document);
|
||||
void setActiveLayer(doc::Layer* layer);
|
||||
void setActiveFrame(doc::frame_t frame);
|
||||
void setSelectedColors(const doc::PalettePicks& picks);
|
||||
bool hasModifiedDocuments() const;
|
||||
void notifyActiveSiteChanged();
|
||||
|
||||
@ -111,6 +113,7 @@ namespace app {
|
||||
virtual void onSetActiveDocument(Doc* doc);
|
||||
virtual void onSetActiveLayer(doc::Layer* layer);
|
||||
virtual void onSetActiveFrame(const doc::frame_t frame);
|
||||
virtual void onSetSelectedColors(const doc::PalettePicks& picks);
|
||||
virtual void onCloseDocument(Doc* doc);
|
||||
|
||||
Doc* lastSelectedDoc() { return m_lastSelectedDoc; }
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -109,6 +110,9 @@ void ContextFlags::updateFlagsFromSite(const Site& site)
|
||||
m_flags |= HasActiveImage;
|
||||
}
|
||||
}
|
||||
|
||||
if (site.selectedColors().picks() > 0)
|
||||
m_flags |= HasSelectedColors;
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -32,6 +33,7 @@ namespace app {
|
||||
ActiveLayerIsVisible = 1 << 11,
|
||||
ActiveLayerIsEditable = 1 << 12,
|
||||
ActiveLayerIsReference = 1 << 13,
|
||||
HasSelectedColors = 1 << 14,
|
||||
};
|
||||
|
||||
ContextFlags();
|
||||
|
@ -466,18 +466,9 @@ int App_get_site(lua_State* L)
|
||||
|
||||
int App_get_range(lua_State* L)
|
||||
{
|
||||
#ifdef ENABLE_UI
|
||||
app::Context* ctx = App::instance()->context();
|
||||
Site site = ctx->activeSite();
|
||||
if (site.sprite() && App::instance()->timeline()) {
|
||||
push_doc_range(L, site, App::instance()->timeline()->range());
|
||||
}
|
||||
else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
#else
|
||||
lua_pushnil(L);
|
||||
#endif
|
||||
push_doc_range(L, site);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,6 @@ namespace tools {
|
||||
|
||||
namespace app {
|
||||
|
||||
class DocRange;
|
||||
class Site;
|
||||
|
||||
namespace script {
|
||||
@ -119,7 +118,7 @@ namespace app {
|
||||
void push_cels(lua_State* L, doc::Layer* layer);
|
||||
void push_cels(lua_State* L, doc::Sprite* sprite);
|
||||
void push_color_space(lua_State* L, const gfx::ColorSpace& cs);
|
||||
void push_doc_range(lua_State* L, Site& site, const DocRange& docRange);
|
||||
void push_doc_range(lua_State* L, Site& site);
|
||||
void push_image(lua_State* L, doc::Image* image);
|
||||
void push_images(lua_State* L, const doc::ObjectIds& images);
|
||||
void push_layers(lua_State* L, const doc::ObjectIds& layers);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -8,6 +8,8 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/context.h"
|
||||
#include "app/doc_range.h"
|
||||
#include "app/script/docobj.h"
|
||||
#include "app/script/engine.h"
|
||||
@ -34,8 +36,11 @@ struct RangeObj { // This is like DocRange but referencing objects with IDs
|
||||
std::set<ObjectId> layers;
|
||||
std::vector<frame_t> frames;
|
||||
std::set<ObjectId> cels;
|
||||
std::vector<color_t> colors;
|
||||
|
||||
RangeObj(Site& site) {
|
||||
const DocRange& docRange = site.range();
|
||||
|
||||
RangeObj(Site& site, const DocRange& docRange) {
|
||||
spriteId = site.sprite()->id();
|
||||
type = docRange.type();
|
||||
|
||||
@ -59,6 +64,9 @@ struct RangeObj { // This is like DocRange but referencing objects with IDs
|
||||
if (site.layer()) layers.insert(site.layer()->id());
|
||||
if (site.cel()) cels.insert(site.cel()->id());
|
||||
}
|
||||
|
||||
if (site.selectedColors().picks() > 0)
|
||||
colors = site.selectedColors().toVectorOfIndexes();
|
||||
}
|
||||
RangeObj(const RangeObj&) = delete;
|
||||
RangeObj& operator=(const RangeObj&) = delete;
|
||||
@ -74,6 +82,9 @@ struct RangeObj { // This is like DocRange but referencing objects with IDs
|
||||
bool contains(const Cel* cel) const {
|
||||
return cels.find(cel->id()) != cels.end();
|
||||
}
|
||||
bool containsColor(const color_t color) const {
|
||||
return (std::find(colors.begin(), colors.end(), color) != colors.end());
|
||||
}
|
||||
};
|
||||
|
||||
int Range_gc(lua_State* L)
|
||||
@ -114,6 +125,14 @@ int Range_contains(lua_State* L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Range_containsColor(lua_State* L)
|
||||
{
|
||||
auto obj = get_obj<RangeObj>(L, 1);
|
||||
color_t color = lua_tointeger(L, 2);
|
||||
lua_pushboolean(L, obj->containsColor(color));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Range_get_isEmpty(lua_State* L)
|
||||
{
|
||||
auto obj = get_obj<RangeObj>(L, 1);
|
||||
@ -181,9 +200,40 @@ int Range_get_editableImages(lua_State* L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Range_get_colors(lua_State* L)
|
||||
{
|
||||
auto obj = get_obj<RangeObj>(L, 1);
|
||||
lua_newtable(L);
|
||||
int j = 1;
|
||||
for (color_t i : obj->colors) {
|
||||
lua_pushinteger(L, i);
|
||||
lua_rawseti(L, -2, j++);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Range_set_colors(lua_State* L)
|
||||
{
|
||||
app::Context* ctx = App::instance()->context();
|
||||
doc::PalettePicks picks;
|
||||
if (lua_istable(L, 2)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, 2) != 0) {
|
||||
int i = lua_tointeger(L, -1);
|
||||
if (i >= picks.size())
|
||||
picks.resize(i+1);
|
||||
picks[i] = true;
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
ctx->setSelectedColors(picks);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg Range_methods[] = {
|
||||
{ "__gc", Range_gc },
|
||||
{ "contains", Range_contains },
|
||||
{ "containsColor", Range_containsColor },
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
@ -196,6 +246,7 @@ const Property Range_properties[] = {
|
||||
{ "cels", Range_get_cels, nullptr },
|
||||
{ "images", Range_get_images, nullptr },
|
||||
{ "editableImages", Range_get_editableImages, nullptr },
|
||||
{ "colors", Range_get_colors, Range_set_colors },
|
||||
{ nullptr, nullptr, nullptr }
|
||||
};
|
||||
|
||||
@ -210,9 +261,9 @@ void register_range_class(lua_State* L)
|
||||
REG_CLASS_PROPERTIES(L, Range);
|
||||
}
|
||||
|
||||
void push_doc_range(lua_State* L, Site& site, const DocRange& docRange)
|
||||
void push_doc_range(lua_State* L, Site& site)
|
||||
{
|
||||
push_new<RangeObj>(L, site, docRange);
|
||||
push_new<RangeObj>(L, site);
|
||||
}
|
||||
|
||||
} // namespace script
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "app/doc_range.h"
|
||||
#include "doc/frame.h"
|
||||
#include "doc/palette_picks.h"
|
||||
#include "doc/selected_objects.h"
|
||||
|
||||
namespace doc {
|
||||
@ -78,6 +79,13 @@ namespace app {
|
||||
const doc::SelectedLayers& selectedLayers() const { return m_range.selectedLayers(); }
|
||||
const doc::SelectedFrames& selectedFrames() const { return m_range.selectedFrames(); }
|
||||
|
||||
// Selected colors selected in the ColorBar
|
||||
const doc::PalettePicks& selectedColors() const { return m_selectedColors; }
|
||||
doc::PalettePicks& selectedColors() { return m_selectedColors; }
|
||||
void selectedColors(const doc::PalettePicks& colors) {
|
||||
m_selectedColors = colors;
|
||||
}
|
||||
|
||||
const doc::SelectedObjects& selectedSlices() const { return m_selectedSlices; }
|
||||
doc::SelectedObjects& selectedSlices() { return m_selectedSlices; }
|
||||
void selectedSlices(const doc::SelectedObjects& set) {
|
||||
@ -95,6 +103,7 @@ namespace app {
|
||||
doc::Layer* m_layer;
|
||||
doc::frame_t m_frame;
|
||||
DocRange m_range;
|
||||
doc::PalettePicks m_selectedColors;
|
||||
doc::SelectedObjects m_selectedSlices;
|
||||
};
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "app/util/clipboard.h"
|
||||
#include "app/util/pal_ops.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/convert_to.h"
|
||||
#include "doc/image.h"
|
||||
@ -189,6 +190,18 @@ int PaletteView::getSelectedEntriesCount() const
|
||||
return m_selectedEntries.picks();
|
||||
}
|
||||
|
||||
void PaletteView::setSelectedEntries(const doc::PalettePicks& entries)
|
||||
{
|
||||
ASSERT(currentPalette());
|
||||
if (!currentPalette())
|
||||
return;
|
||||
|
||||
m_selectedEntries = entries;
|
||||
m_selectedEntries.resize(currentPalette()->size());
|
||||
m_currentEntry = m_selectedEntries.firstPick();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
app::Color PaletteView::getColorByPosition(const gfx::Point& pos)
|
||||
{
|
||||
gfx::Point relPos = pos - bounds().origin();
|
||||
@ -777,58 +790,14 @@ PaletteView::Hit PaletteView::hitTest(const gfx::Point& pos)
|
||||
void PaletteView::dropColors(int beforeIndex)
|
||||
{
|
||||
Palette palette(*currentPalette());
|
||||
if (beforeIndex >= palette.size()) {
|
||||
palette.resize(beforeIndex);
|
||||
m_selectedEntries.resize(palette.size());
|
||||
}
|
||||
|
||||
Palette newPalette(palette);
|
||||
Remap remap(palette.size());
|
||||
|
||||
// Copy colors
|
||||
if (m_copy) {
|
||||
int picks = m_selectedEntries.picks();
|
||||
ASSERT(picks >= 1);
|
||||
|
||||
remap = create_remap_to_expand_palette(palette.size()+picks,
|
||||
picks,
|
||||
beforeIndex);
|
||||
|
||||
newPalette.resize(palette.size()+picks);
|
||||
for (int i=0; i<palette.size(); ++i)
|
||||
newPalette.setEntry(remap[i], palette.getEntry(i));
|
||||
|
||||
for (int i=0, j=0; i<palette.size(); ++i) {
|
||||
if (m_selectedEntries[i])
|
||||
newPalette.setEntry(beforeIndex + (j++), palette.getEntry(i));
|
||||
}
|
||||
|
||||
for (int i=0, j=0; i<palette.size(); ++i) {
|
||||
if (m_selectedEntries[i]) {
|
||||
if (m_currentEntry == i) {
|
||||
m_currentEntry = beforeIndex + j;
|
||||
break;
|
||||
}
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<palette.size(); ++i)
|
||||
m_selectedEntries[i] = (i >= beforeIndex && i < beforeIndex + picks);
|
||||
}
|
||||
// Move colors
|
||||
else {
|
||||
remap = create_remap_to_move_picks(m_selectedEntries, beforeIndex);
|
||||
|
||||
auto oldSelectedCopies = m_selectedEntries;
|
||||
for (int i=0; i<palette.size(); ++i) {
|
||||
newPalette.setEntry(remap[i], palette.getEntry(i));
|
||||
m_selectedEntries[remap[i]] = oldSelectedCopies[i];
|
||||
}
|
||||
|
||||
m_currentEntry = remap[m_currentEntry];
|
||||
}
|
||||
|
||||
move_or_copy_palette_colors(
|
||||
palette,
|
||||
newPalette,
|
||||
m_selectedEntries,
|
||||
m_currentEntry,
|
||||
beforeIndex,
|
||||
m_copy);
|
||||
setNewPalette(&palette, &newPalette,
|
||||
PaletteViewModification::DRAGANDDROP);
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ namespace app {
|
||||
bool getSelectedRange(int& index1, int& index2) const;
|
||||
void getSelectedEntries(doc::PalettePicks& entries) const;
|
||||
int getSelectedEntriesCount() const;
|
||||
void setSelectedEntries(const doc::PalettePicks& entries);
|
||||
|
||||
// IColorSource
|
||||
app::Color getColorByPosition(const gfx::Point& pos) override;
|
||||
|
@ -166,6 +166,16 @@ void UIContext::onSetActiveFrame(const doc::frame_t frame)
|
||||
Context::onSetActiveFrame(frame);
|
||||
}
|
||||
|
||||
void UIContext::onSetSelectedColors(const doc::PalettePicks& picks)
|
||||
{
|
||||
if (DocView* docView = activeView()) {
|
||||
if (ColorBar* colorBar = ColorBar::instance())
|
||||
colorBar->getPaletteView()->setSelectedEntries(picks);
|
||||
}
|
||||
else if (!isUIAvailable())
|
||||
Context::onSetSelectedColors(picks);
|
||||
}
|
||||
|
||||
DocView* UIContext::getFirstDocView(Doc* document) const
|
||||
{
|
||||
Workspace* workspace = App::instance()->workspace();
|
||||
@ -294,7 +304,7 @@ void UIContext::onGetActiveSite(Site* site) const
|
||||
view->getSite(site);
|
||||
|
||||
if (site->sprite()) {
|
||||
// Selected layers
|
||||
// Selected range in the timeline
|
||||
Timeline* timeline = App::instance()->timeline();
|
||||
if (timeline &&
|
||||
timeline->range().enabled()) {
|
||||
@ -305,6 +315,10 @@ void UIContext::onGetActiveSite(Site* site) const
|
||||
if (colorBar &&
|
||||
colorBar->getPaletteView()->getSelectedEntriesCount() > 0) {
|
||||
site->focus(Site::InColorBar);
|
||||
|
||||
doc::PalettePicks picks;
|
||||
colorBar->getPaletteView()->getSelectedEntries(picks);
|
||||
site->selectedColors(picks);
|
||||
}
|
||||
else {
|
||||
site->focus(Site::InEditor);
|
||||
|
@ -56,6 +56,7 @@ namespace app {
|
||||
void onSetActiveDocument(Doc* doc) override;
|
||||
void onSetActiveLayer(doc::Layer* layer) override;
|
||||
void onSetActiveFrame(const doc::frame_t frame) override;
|
||||
void onSetSelectedColors(const doc::PalettePicks& picks) override;
|
||||
void onCloseDocument(Doc* doc) override;
|
||||
|
||||
private:
|
||||
|
80
src/app/util/pal_ops.cpp
Normal file
80
src/app/util/pal_ops.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/util/pal_ops.h"
|
||||
|
||||
#include "doc/palette.h"
|
||||
#include "doc/palette_picks.h"
|
||||
#include "doc/remap.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
void move_or_copy_palette_colors(
|
||||
doc::Palette& palette,
|
||||
doc::Palette& newPalette,
|
||||
doc::PalettePicks& picks,
|
||||
int& currentEntry,
|
||||
const int beforeIndex,
|
||||
const bool copy)
|
||||
{
|
||||
if (beforeIndex >= palette.size()) {
|
||||
palette.resize(beforeIndex); // TODO is need to resize the
|
||||
// palette? why not "const Palette& palette"
|
||||
picks.resize(palette.size());
|
||||
}
|
||||
|
||||
palette.copyColorsTo(&newPalette);
|
||||
doc::Remap remap(palette.size());
|
||||
|
||||
// Copy colors
|
||||
if (copy) {
|
||||
int npicks = picks.picks();
|
||||
ASSERT(npicks >= 1);
|
||||
|
||||
remap = doc::create_remap_to_expand_palette(palette.size()+npicks,
|
||||
npicks, beforeIndex);
|
||||
|
||||
newPalette.resize(palette.size()+npicks);
|
||||
for (int i=0; i<palette.size(); ++i)
|
||||
newPalette.setEntry(remap[i], palette.getEntry(i));
|
||||
|
||||
for (int i=0, j=0; i<palette.size(); ++i) {
|
||||
if (picks[i])
|
||||
newPalette.setEntry(beforeIndex + (j++), palette.getEntry(i));
|
||||
}
|
||||
|
||||
for (int i=0, j=0; i<palette.size(); ++i) {
|
||||
if (picks[i]) {
|
||||
if (currentEntry == i) {
|
||||
currentEntry = beforeIndex + j;
|
||||
break;
|
||||
}
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<palette.size(); ++i)
|
||||
picks[i] = (i >= beforeIndex && i < beforeIndex + npicks);
|
||||
}
|
||||
// Move colors
|
||||
else {
|
||||
remap = doc::create_remap_to_move_picks(picks, beforeIndex);
|
||||
|
||||
auto oldPicks = picks;
|
||||
for (int i=0; i<palette.size(); ++i) {
|
||||
newPalette.setEntry(remap[i], palette.getEntry(i));
|
||||
picks[remap[i]] = oldPicks[i];
|
||||
}
|
||||
|
||||
currentEntry = remap[currentEntry];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace app
|
29
src/app/util/pal_ops.h
Normal file
29
src/app/util/pal_ops.h
Normal file
@ -0,0 +1,29 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef APP_UTIL_PAL_OPS_H_INCLUDED
|
||||
#define APP_UTIL_PAL_OPS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
namespace doc {
|
||||
class Palette;
|
||||
class PalettePicks;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
class Tx;
|
||||
|
||||
void move_or_copy_palette_colors(
|
||||
doc::Palette& palette,
|
||||
doc::Palette& newPalette,
|
||||
doc::PalettePicks& picks,
|
||||
int& currentEntry,
|
||||
const int beforeIndex,
|
||||
const bool copy);
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
@ -1,4 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2019 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -8,6 +9,8 @@
|
||||
#define DOC_PALETTE_PICKS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "doc/color.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
@ -68,6 +71,15 @@ namespace doc {
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::vector<color_t> toVectorOfIndexes() const {
|
||||
std::vector<color_t> result(picks());
|
||||
for (color_t i=0, j=0; i<size(); ++i) {
|
||||
if (m_items[i])
|
||||
result[j++] = i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
list_type m_items;
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
# Aseprite
|
||||
# Copyright (C) 2019 Igara Studio S.A.
|
||||
# Copyright (C) 2001-2017 David Capello
|
||||
|
||||
add_library(filters-lib
|
||||
@ -7,6 +8,7 @@ add_library(filters-lib
|
||||
color_curve_filter.cpp
|
||||
convolution_matrix.cpp
|
||||
convolution_matrix_filter.cpp
|
||||
filter.cpp
|
||||
hue_saturation_filter.cpp
|
||||
invert_color_filter.cpp
|
||||
median_filter.cpp
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -52,15 +53,8 @@ void BrightnessContrastFilter::setContrast(double contrast)
|
||||
void BrightnessContrastFilter::applyToRgba(FilterManager* filterMgr)
|
||||
{
|
||||
FilterIndexedData* fid = filterMgr->getIndexedData();
|
||||
|
||||
if (filterMgr->isFirstRow()) {
|
||||
m_picks = fid->getPalettePicks();
|
||||
m_usePalette = (m_picks.picks() > 0);
|
||||
if (m_usePalette)
|
||||
applyToPalette(filterMgr);
|
||||
}
|
||||
|
||||
const Palette* pal = fid->getPalette();
|
||||
Palette* newPal = (m_usePaletteOnRGB ? fid->getNewPalette(): nullptr);
|
||||
const uint32_t* src_address = (uint32_t*)filterMgr->getSourceAddress();
|
||||
uint32_t* dst_address = (uint32_t*)filterMgr->getDestinationAddress();
|
||||
const int w = filterMgr->getWidth();
|
||||
@ -75,14 +69,14 @@ void BrightnessContrastFilter::applyToRgba(FilterManager* filterMgr)
|
||||
|
||||
color_t c = *(src_address++);
|
||||
|
||||
if (m_usePalette) {
|
||||
if (newPal) {
|
||||
int i =
|
||||
pal->findExactMatch(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c),
|
||||
rgba_geta(c), -1);
|
||||
if (i >= 0)
|
||||
c = fid->getNewPalette()->getEntry(i);
|
||||
c = newPal->getEntry(i);
|
||||
}
|
||||
else {
|
||||
applyFilterToRgb(target, c);
|
||||
@ -120,18 +114,11 @@ void BrightnessContrastFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
{
|
||||
FilterIndexedData* fid = filterMgr->getIndexedData();
|
||||
|
||||
// Apply filter to color palette if there is no selection
|
||||
if (!filterMgr->isMaskActive()) {
|
||||
if (!filterMgr->isFirstRow())
|
||||
return;
|
||||
|
||||
m_picks = fid->getPalettePicks();
|
||||
if (m_picks.picks() == 0)
|
||||
m_picks.all();
|
||||
|
||||
applyToPalette(filterMgr);
|
||||
// Apply filter to pixels if there is selection (in other case, the
|
||||
// change is global, so we have already applied the filter to the
|
||||
// palette).
|
||||
if (!filterMgr->isMaskActive())
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply filter to color region
|
||||
const Target target = filterMgr->getTarget();
|
||||
@ -157,7 +144,8 @@ void BrightnessContrastFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
}
|
||||
}
|
||||
|
||||
void BrightnessContrastFilter::applyToPalette(FilterManager* filterMgr)
|
||||
void BrightnessContrastFilter::onApplyToPalette(FilterManager* filterMgr,
|
||||
const PalettePicks& picks)
|
||||
{
|
||||
const Target target = filterMgr->getTarget();
|
||||
FilterIndexedData* fid = filterMgr->getIndexedData();
|
||||
@ -165,7 +153,7 @@ void BrightnessContrastFilter::applyToPalette(FilterManager* filterMgr)
|
||||
Palette* newPal = fid->getNewPalette();
|
||||
|
||||
int i = 0;
|
||||
for (bool state : m_picks) {
|
||||
for (bool state : picks) {
|
||||
if (!state) {
|
||||
++i;
|
||||
continue;
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
namespace filters {
|
||||
|
||||
class BrightnessContrastFilter : public Filter {
|
||||
class BrightnessContrastFilter : public FilterWithPalette {
|
||||
public:
|
||||
BrightnessContrastFilter();
|
||||
|
||||
@ -28,19 +28,18 @@ namespace filters {
|
||||
void setContrast(double contrast);
|
||||
|
||||
// Filter implementation
|
||||
const char* getName();
|
||||
void applyToRgba(FilterManager* filterMgr);
|
||||
void applyToGrayscale(FilterManager* filterMgr);
|
||||
void applyToIndexed(FilterManager* filterMgr);
|
||||
const char* getName() override;
|
||||
void applyToRgba(FilterManager* filterMgr) override;
|
||||
void applyToGrayscale(FilterManager* filterMgr) override;
|
||||
void applyToIndexed(FilterManager* filterMgr) override;
|
||||
|
||||
private:
|
||||
void applyToPalette(FilterManager* filterMgr);
|
||||
void onApplyToPalette(FilterManager* filterMgr,
|
||||
const doc::PalettePicks& picks) override;
|
||||
void applyFilterToRgb(const Target target, doc::color_t& color);
|
||||
void updateMap();
|
||||
|
||||
double m_brightness, m_contrast;
|
||||
doc::PalettePicks m_picks;
|
||||
bool m_usePalette;
|
||||
std::vector<int> m_cmap;
|
||||
};
|
||||
|
||||
|
60
src/filters/filter.cpp
Normal file
60
src/filters/filter.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "filters/filter.h"
|
||||
|
||||
#include "doc/palette.h"
|
||||
#include "doc/palette_picks.h"
|
||||
#include "filters/filter_indexed_data.h"
|
||||
#include "filters/filter_manager.h"
|
||||
|
||||
namespace filters {
|
||||
|
||||
FilterWithPalette::FilterWithPalette()
|
||||
: m_usePaletteOnRGB(false)
|
||||
{
|
||||
}
|
||||
|
||||
void FilterWithPalette::applyToPalette(FilterManager* filterMgr)
|
||||
{
|
||||
FilterIndexedData* fid = filterMgr->getIndexedData();
|
||||
doc::PalettePicks picks = fid->getPalettePicks();
|
||||
|
||||
switch (filterMgr->pixelFormat()) {
|
||||
|
||||
case doc::IMAGE_RGB:
|
||||
m_usePaletteOnRGB = (picks.picks() > 0);
|
||||
if (!m_usePaletteOnRGB)
|
||||
return;
|
||||
break;
|
||||
|
||||
case doc::IMAGE_INDEXED:
|
||||
// If there is a selection, we don't apply the filter to color
|
||||
// palette, instead we apply the filter to the pixels as an RGB
|
||||
// image (using closest colors from the palette)
|
||||
if (filterMgr->isMaskActive())
|
||||
return;
|
||||
|
||||
// If there are no picks, we apply the filter to the whole palette.
|
||||
if (picks.picks() == 0) {
|
||||
picks.resize(fid->getPalette()->size());
|
||||
picks.all();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// We cannot change the palette of a grayscale image
|
||||
return;
|
||||
}
|
||||
|
||||
onApplyToPalette(filterMgr, picks);
|
||||
}
|
||||
|
||||
} // namespace filters
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -8,6 +9,10 @@
|
||||
#define FILTERS_FILTER_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
namespace doc {
|
||||
class PalettePicks;
|
||||
}
|
||||
|
||||
namespace filters {
|
||||
|
||||
class FilterManager;
|
||||
@ -37,6 +42,22 @@ namespace filters {
|
||||
// each pixel.
|
||||
virtual void applyToIndexed(FilterManager* filterMgr) = 0;
|
||||
|
||||
// Applies the filter to the color palette.
|
||||
virtual void applyToPalette(FilterManager* filterMgr) { }
|
||||
};
|
||||
|
||||
// Filter that support applying it only to palette colors.
|
||||
class FilterWithPalette : public Filter {
|
||||
public:
|
||||
FilterWithPalette();
|
||||
void applyToPalette(FilterManager* filterMgr) override;
|
||||
|
||||
protected:
|
||||
virtual void onApplyToPalette(FilterManager* filterMgr,
|
||||
const doc::PalettePicks& picks) = 0;
|
||||
|
||||
// Use the palette to replace colors in RGB images
|
||||
bool m_usePaletteOnRGB;
|
||||
};
|
||||
|
||||
} // namespace filters
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -8,6 +9,7 @@
|
||||
#define FILTERS_FILTER_MANAGER_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "doc/pixel_format.h"
|
||||
#include "filters/target.h"
|
||||
|
||||
namespace doc {
|
||||
@ -27,6 +29,8 @@ namespace filters {
|
||||
public:
|
||||
virtual ~FilterManager() { }
|
||||
|
||||
virtual doc::PixelFormat pixelFormat() const = 0;
|
||||
|
||||
// Gets the address of the first pixel which has the original color
|
||||
// to apply the filter.
|
||||
virtual const void* getSourceAddress() = 0;
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2017-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -12,6 +13,7 @@
|
||||
|
||||
#include "doc/image.h"
|
||||
#include "doc/palette.h"
|
||||
#include "doc/palette_picks.h"
|
||||
#include "doc/rgbmap.h"
|
||||
#include "filters/filter_indexed_data.h"
|
||||
#include "filters/filter_manager.h"
|
||||
@ -67,15 +69,8 @@ void HueSaturationFilter::setAlpha(double a)
|
||||
void HueSaturationFilter::applyToRgba(FilterManager* filterMgr)
|
||||
{
|
||||
FilterIndexedData* fid = filterMgr->getIndexedData();
|
||||
|
||||
if (filterMgr->isFirstRow()) {
|
||||
m_picks = fid->getPalettePicks();
|
||||
m_usePalette = (m_picks.picks() > 0);
|
||||
if (m_usePalette)
|
||||
applyToPalette(filterMgr);
|
||||
}
|
||||
|
||||
const Palette* pal = fid->getPalette();
|
||||
Palette* newPal = (m_usePaletteOnRGB ? fid->getNewPalette(): nullptr);
|
||||
const uint32_t* src_address = (uint32_t*)filterMgr->getSourceAddress();
|
||||
uint32_t* dst_address = (uint32_t*)filterMgr->getDestinationAddress();
|
||||
const int w = filterMgr->getWidth();
|
||||
@ -90,14 +85,14 @@ void HueSaturationFilter::applyToRgba(FilterManager* filterMgr)
|
||||
|
||||
color_t c = *(src_address++);
|
||||
|
||||
if (m_usePalette) {
|
||||
if (newPal) {
|
||||
int i =
|
||||
pal->findExactMatch(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c),
|
||||
rgba_geta(c), -1);
|
||||
if (i >= 0)
|
||||
c = fid->getNewPalette()->getEntry(i);
|
||||
c = newPal->getEntry(i);
|
||||
}
|
||||
else {
|
||||
applyFilterToRgb(target, c);
|
||||
@ -148,22 +143,14 @@ void HueSaturationFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
|
||||
void HueSaturationFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
{
|
||||
FilterIndexedData* fid = filterMgr->getIndexedData();
|
||||
|
||||
// Apply filter to color palette if there is no selection
|
||||
if (!filterMgr->isMaskActive()) {
|
||||
if (!filterMgr->isFirstRow())
|
||||
return;
|
||||
|
||||
m_picks = fid->getPalettePicks();
|
||||
if (m_picks.picks() == 0)
|
||||
m_picks.all();
|
||||
|
||||
applyToPalette(filterMgr);
|
||||
// Apply filter to pixels if there is selection (in other case, the
|
||||
// change is global, so we have already applied the filter to the
|
||||
// palette).
|
||||
if (!filterMgr->isMaskActive())
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply filter to color region
|
||||
FilterIndexedData* fid = filterMgr->getIndexedData();
|
||||
const Target target = filterMgr->getTarget();
|
||||
const Palette* pal = fid->getPalette();
|
||||
const RgbMap* rgbmap = fid->getRgbMap();
|
||||
@ -187,15 +174,16 @@ void HueSaturationFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
}
|
||||
}
|
||||
|
||||
void HueSaturationFilter::applyToPalette(FilterManager* filterMgr)
|
||||
void HueSaturationFilter::onApplyToPalette(FilterManager* filterMgr,
|
||||
const PalettePicks& picks)
|
||||
{
|
||||
const Target target = filterMgr->getTarget();
|
||||
FilterIndexedData* fid = filterMgr->getIndexedData();
|
||||
const Target target = filterMgr->getTarget();
|
||||
const Palette* pal = fid->getPalette();
|
||||
Palette* newPal = fid->getNewPalette();
|
||||
|
||||
int i = 0;
|
||||
for (bool state : m_picks) {
|
||||
for (bool state : picks) {
|
||||
if (!state) {
|
||||
++i;
|
||||
continue;
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2017-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -9,13 +10,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "doc/color.h"
|
||||
#include "doc/palette_picks.h"
|
||||
#include "filters/filter.h"
|
||||
#include "filters/target.h"
|
||||
|
||||
namespace filters {
|
||||
|
||||
class HueSaturationFilter : public Filter {
|
||||
class HueSaturationFilter : public FilterWithPalette {
|
||||
public:
|
||||
enum class Mode { HSL, HSV };
|
||||
|
||||
@ -28,13 +28,15 @@ namespace filters {
|
||||
void setAlpha(double a);
|
||||
|
||||
// Filter implementation
|
||||
const char* getName();
|
||||
void applyToRgba(FilterManager* filterMgr);
|
||||
void applyToGrayscale(FilterManager* filterMgr);
|
||||
void applyToIndexed(FilterManager* filterMgr);
|
||||
const char* getName() override;
|
||||
void applyToRgba(FilterManager* filterMgr) override;
|
||||
void applyToGrayscale(FilterManager* filterMgr) override;
|
||||
void applyToIndexed(FilterManager* filterMgr) override;
|
||||
|
||||
private:
|
||||
void applyToPalette(FilterManager* filterMgr);
|
||||
void onApplyToPalette(FilterManager* filterMgr,
|
||||
const doc::PalettePicks& picks) override;
|
||||
|
||||
template<class T,
|
||||
double (T::*get_lightness)() const,
|
||||
void (T::*set_lightness)(double)>
|
||||
@ -43,8 +45,6 @@ namespace filters {
|
||||
|
||||
Mode m_mode;
|
||||
double m_h, m_s, m_l, m_a;
|
||||
doc::PalettePicks m_picks;
|
||||
bool m_usePalette;
|
||||
};
|
||||
|
||||
} // namespace filters
|
||||
|
Loading…
x
Reference in New Issue
Block a user