Add option to "remap" colors after a drag-and-drop (related to #563)

This commit is contained in:
David Capello 2015-03-23 12:57:59 -03:00
parent d14e4e8896
commit b13601117f
11 changed files with 168 additions and 8 deletions

View File

@ -85,6 +85,7 @@ add_library(app-lib
cmd/layer_from_background.cpp
cmd/move_cel.cpp
cmd/move_layer.cpp
cmd/remap_colors.cpp
cmd/remove_cel.cpp
cmd/remove_frame.cpp
cmd/remove_frame_tag.cpp

View File

@ -0,0 +1,45 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/cmd/remap_colors.h"
#include "doc/image.h"
#include "doc/remap.h"
#include "doc/sprite.h"
#include "doc/image_bits.h"
namespace app {
namespace cmd {
using namespace doc;
RemapColors::RemapColors(Sprite* sprite, const Remap& remap)
: WithSprite(sprite)
, m_remap(remap)
{
}
void RemapColors::onExecute()
{
Sprite* spr = sprite();
if (spr->pixelFormat() == IMAGE_INDEXED)
spr->remapImages(0, spr->lastFrame(), m_remap);
}
void RemapColors::onUndo()
{
Sprite* spr = this->sprite();
if (spr->pixelFormat() == IMAGE_INDEXED)
spr->remapImages(0, spr->lastFrame(), m_remap.invert());
}
} // namespace cmd
} // namespace app

View File

@ -0,0 +1,39 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifndef APP_CMD_REMAP_COLORS_H_INCLUDED
#define APP_CMD_REMAP_COLORS_H_INCLUDED
#pragma once
#include "app/cmd.h"
#include "app/cmd/with_sprite.h"
#include "doc/remap.h"
namespace app {
namespace cmd {
using namespace doc;
class RemapColors : public Cmd
, public WithSprite {
public:
RemapColors(Sprite* sprite, const Remap& remap);
protected:
void onExecute() override;
void onUndo() override;
size_t onMemSize() const override {
return sizeof(*this) + m_remap.getMemSize();
}
private:
Remap m_remap;
};
} // namespace cmd
} // namespace app
#endif

View File

@ -5,8 +5,8 @@
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifndef APP_CMD_SET_PALETTE_COLORS_H_INCLUDED
#define APP_CMD_SET_PALETTE_COLORS_H_INCLUDED
#ifndef APP_CMD_SET_PALETTE_H_INCLUDED
#define APP_CMD_SET_PALETTE_H_INCLUDED
#pragma once
#include "app/cmd.h"

View File

@ -11,6 +11,7 @@
#include "app/ui/color_bar.h"
#include "app/cmd/remap_colors.h"
#include "app/cmd/set_palette.h"
#include "app/color.h"
#include "app/commands/commands.h"
@ -27,6 +28,7 @@
#include "base/bind.h"
#include "doc/image.h"
#include "doc/palette.h"
#include "doc/remap.h"
#include "she/surface.h"
#include "ui/graphics.h"
#include "ui/menu.h"
@ -74,9 +76,11 @@ ColorBar::ColorBar(int align)
: Box(align)
, m_paletteButton("Edit Palette")
, m_paletteView(true, this)
, m_remapButton("Remap")
, m_fgColor(app::Color::fromRgb(255, 255, 255), IMAGE_RGB)
, m_bgColor(app::Color::fromRgb(0, 0, 0), IMAGE_RGB)
, m_lock(false)
, m_remap(nullptr)
{
m_instance = this;
@ -97,11 +101,15 @@ ColorBar::ColorBar(int align)
m_scrollableView.attachToView(&m_paletteView);
m_scrollableView.setExpansive(true);
m_remapButton.setVisible(false);
addChild(&m_paletteButton);
addChild(&m_scrollableView);
addChild(&m_remapButton);
addChild(&m_fgColor);
addChild(&m_bgColor);
m_remapButton.Click.connect(Bind<void>(&ColorBar::onRemapButtonClick, this));
m_fgColor.Change.connect(&ColorBar::onFgColorButtonChange, this);
m_bgColor.Change.connect(&ColorBar::onBgColorButtonChange, this);
@ -194,6 +202,33 @@ void ColorBar::onPaletteButtonDropDownClick()
}
}
void ColorBar::onRemapButtonClick()
{
ASSERT(m_remap);
try {
ContextWriter writer(UIContext::instance());
Sprite* sprite = writer.sprite();
frame_t frame = writer.frame();
if (sprite) {
Transaction transaction(writer.context(), "Remap Colors", ModifyDocument);
transaction.execute(new cmd::RemapColors(sprite, *m_remap));
transaction.commit();
delete m_remap;
m_remap = nullptr;
}
update_screen_for_document(writer.document());
}
catch (base::Exception& e) {
Console::showException(e);
}
m_remapButton.setVisible(false);
layout();
}
void ColorBar::onPaletteViewIndexChange(int index, ui::MouseButtons buttons)
{
m_lock = true;
@ -210,6 +245,15 @@ void ColorBar::onPaletteViewIndexChange(int index, ui::MouseButtons buttons)
void ColorBar::onPaletteViewRemapColors(const Remap& remap, const Palette* newPalette)
{
if (!m_remap) {
m_remap = new doc::Remap(remap);
m_remapButton.setVisible(true);
layout();
}
else {
m_remap->merge(remap);
}
try {
ContextWriter writer(UIContext::instance());
Sprite* sprite = writer.sprite();

View File

@ -55,6 +55,7 @@ namespace app {
protected:
void onPaletteButtonClick();
void onPaletteButtonDropDownClick();
void onRemapButtonClick();
void onPaletteIndexChange(PaletteIndexChangeEvent& ev);
void onFgColorButtonChange(const app::Color& color);
void onBgColorButtonChange(const app::Color& color);
@ -76,9 +77,11 @@ namespace app {
PalettePopup m_palettePopup;
ScrollableView m_scrollableView;
PaletteView m_paletteView;
ui::Button m_remapButton;
ColorButton m_fgColor;
ColorButton m_bgColor;
bool m_lock;
doc::Remap* m_remap;
};
} // namespace app

View File

@ -26,6 +26,7 @@
#include "doc/pixel_format.h"
#include "doc/primitives.h"
#include "doc/primitives_fast.h"
#include "doc/remap.h"
#include "doc/rgbmap.h"
#include "doc/sprite.h"

View File

@ -44,4 +44,19 @@ Remap Remap::moveSelectedEntriesTo(const std::vector<bool>& selectedEntries, int
return map;
}
void Remap::merge(const Remap& other)
{
for (int i=0; i<size(); ++i) {
m_map[i] = other[m_map[i]];
}
}
Remap Remap::invert() const
{
Remap inv(size());
for (int i=0; i<size(); ++i)
inv.map(operator[](i), i);
return inv;
}
} // namespace doc

View File

@ -37,6 +37,13 @@ namespace doc {
return m_map[index];
}
void merge(const Remap& other);
Remap invert() const;
int getMemSize() const {
return sizeof(*this) + sizeof(int)*size();
}
private:
std::vector<int> m_map;
};

View File

@ -13,11 +13,15 @@
#include "base/memory.h"
#include "base/remove_from_container.h"
#include "base/unique_ptr.h"
#include "doc/cel.h"
#include "doc/cels_range.h"
#include "doc/doc.h"
#include "doc/frame_tag.h"
#include "doc/image_bits.h"
#include "doc/layer.h"
#include "doc/palette.h"
#include "doc/primitives.h"
#include "doc/remap.h"
#include "doc/rgbmap.h"
#include <cstring>
#include <vector>
@ -448,12 +452,12 @@ void Sprite::getImages(std::vector<Image*>& images) const
images.push_back(cel->image());
}
void Sprite::remapImages(frame_t frameFrom, frame_t frameTo, const std::vector<uint8_t>& mapping)
void Sprite::remapImages(frame_t frameFrom, frame_t frameTo, const Remap& remap)
{
ASSERT(m_format == IMAGE_INDEXED);
ASSERT(mapping.size() == 256);
ASSERT(remap.size() == 256);
for (Cel* cel : cels()) {
for (const Cel* cel : uniqueCels()) {
// Remap this Cel because is inside the specified range
if (cel->frame() >= frameFrom &&
cel->frame() <= frameTo) {
@ -464,7 +468,7 @@ void Sprite::remapImages(frame_t frameFrom, frame_t frameTo, const std::vector<u
end = bits.end();
for (; it != end; ++it)
*it = mapping[*it];
*it = remap[*it];
}
}
}

View File

@ -33,6 +33,7 @@ namespace doc {
class LayerImage;
class Mask;
class Palette;
class Remap;
class RgbMap;
typedef std::vector<Palette*> PalettesList;
@ -134,7 +135,7 @@ namespace doc {
void replaceImage(ObjectId curImageId, const ImageRef& newImage);
void getImages(std::vector<Image*>& images) const;
void remapImages(frame_t frameFrom, frame_t frameTo, const std::vector<uint8_t>& mapping);
void remapImages(frame_t frameFrom, frame_t frameTo, const Remap& remap);
void pickCels(int x, int y, frame_t frame, int opacityThreshold, CelList& cels) const;
CelsRange cels() const;