mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-14 04:19:12 +00:00
Move the active mask from Sprite class to Document.
+ Removed masks and paths repositories. + Added Document::isMaskVisible and Document::setMaskVisible methods.
This commit is contained in:
parent
f412c8450b
commit
0b495085cc
@ -66,15 +66,15 @@ void ClearCommand::onExecute(Context* context)
|
||||
{
|
||||
ActiveDocumentWriter document(context);
|
||||
Sprite* sprite(document->getSprite());
|
||||
bool empty_mask = sprite->getMask()->is_empty();
|
||||
bool visibleMask = document->isMaskVisible();
|
||||
{
|
||||
UndoTransaction undoTransaction(document, "Clear");
|
||||
undoTransaction.clearMask(app_get_color_to_clear_layer(sprite->getCurrentLayer()));
|
||||
if (!empty_mask)
|
||||
if (visibleMask)
|
||||
undoTransaction.deselectMask();
|
||||
undoTransaction.commit();
|
||||
}
|
||||
if (!empty_mask)
|
||||
if (visibleMask)
|
||||
document->generateMaskBoundaries();
|
||||
update_screen_for_document(document);
|
||||
}
|
||||
|
@ -526,11 +526,10 @@ void ConfigureTools::onSetGridClick()
|
||||
try {
|
||||
// TODO use the same context as in ConfigureTools::onExecute
|
||||
const ActiveDocumentReader document(UIContext::instance());
|
||||
const Sprite* sprite(document ? document->getSprite(): 0);
|
||||
|
||||
if (sprite && sprite->getMask() && sprite->getMask()->bitmap) {
|
||||
Rect bounds(sprite->getMask()->x, sprite->getMask()->y,
|
||||
sprite->getMask()->w, sprite->getMask()->h);
|
||||
if (document && document->isMaskVisible()) {
|
||||
const Mask* mask(document->getMask());
|
||||
Rect bounds(mask->x, mask->y, mask->w, mask->h);
|
||||
|
||||
UIContext::instance()->getSettings()->setGridBounds(bounds);
|
||||
|
||||
|
@ -54,8 +54,7 @@ bool CopyCommand::onEnabled(Context* context)
|
||||
(sprite->getCurrentLayer()) &&
|
||||
(sprite->getCurrentLayer()->is_readable()) &&
|
||||
(sprite->getCurrentLayer()->is_writable()) &&
|
||||
(sprite->getMask()) &&
|
||||
(sprite->getMask()->bitmap))
|
||||
(document->isMaskVisible()))
|
||||
return sprite->getCurrentImage() ? true: false;
|
||||
else
|
||||
return false;
|
||||
|
@ -56,26 +56,19 @@ CropSpriteCommand::CropSpriteCommand()
|
||||
bool CropSpriteCommand::onEnabled(Context* context)
|
||||
{
|
||||
const ActiveDocumentReader document(context);
|
||||
const Sprite* sprite(document ? document->getSprite(): 0);
|
||||
return
|
||||
sprite != NULL &&
|
||||
sprite->getMask() != NULL &&
|
||||
sprite->getMask()->bitmap != NULL;
|
||||
return document && document->isMaskVisible();
|
||||
}
|
||||
|
||||
void CropSpriteCommand::onExecute(Context* context)
|
||||
{
|
||||
ActiveDocumentWriter document(context);
|
||||
Sprite* sprite(document->getSprite());
|
||||
const Sprite* sprite(document->getSprite());
|
||||
const Mask* mask(document->getMask());
|
||||
{
|
||||
UndoTransaction undoTransaction(document, "Sprite Crop");
|
||||
int bgcolor = color_utils::color_for_image(app_get_colorbar()->getBgColor(), sprite->getImgType());
|
||||
|
||||
undoTransaction.cropSprite(sprite->getMask()->x,
|
||||
sprite->getMask()->y,
|
||||
sprite->getMask()->w,
|
||||
sprite->getMask()->h,
|
||||
bgcolor);
|
||||
undoTransaction.cropSprite(mask->x, mask->y, mask->w, mask->h, bgcolor);
|
||||
undoTransaction.commit();
|
||||
}
|
||||
document->generateMaskBoundaries();
|
||||
|
@ -54,8 +54,7 @@ bool CutCommand::onEnabled(Context* context)
|
||||
(sprite->getCurrentLayer()) &&
|
||||
(sprite->getCurrentLayer()->is_readable()) &&
|
||||
(sprite->getCurrentLayer()->is_writable()) &&
|
||||
(sprite->getMask()) &&
|
||||
(sprite->getMask()->bitmap))
|
||||
(document->isMaskVisible()))
|
||||
return sprite->getCurrentImage() ? true: false;
|
||||
else
|
||||
return false;
|
||||
|
@ -49,8 +49,7 @@ DeselectMaskCommand::DeselectMaskCommand()
|
||||
bool DeselectMaskCommand::onEnabled(Context* context)
|
||||
{
|
||||
const ActiveDocumentReader document(context);
|
||||
const Sprite* sprite(document ? document->getSprite(): 0);
|
||||
return sprite && !sprite->getMask()->is_empty();
|
||||
return document && document->isMaskVisible();
|
||||
}
|
||||
|
||||
void DeselectMaskCommand::onExecute(Context* context)
|
||||
|
@ -101,8 +101,9 @@ void FlipCommand::onExecute(Context* context)
|
||||
image = sprite->getCurrentImage(&x, &y);
|
||||
if (!image)
|
||||
return;
|
||||
// mask is empty?
|
||||
if (sprite->getMask()->is_empty()) {
|
||||
|
||||
// Mask is empty?
|
||||
if (!document->isMaskVisible()) {
|
||||
// so we flip the entire image
|
||||
x1 = 0;
|
||||
y1 = 0;
|
||||
@ -111,10 +112,10 @@ void FlipCommand::onExecute(Context* context)
|
||||
}
|
||||
else {
|
||||
// apply the cel offset
|
||||
x1 = sprite->getMask()->x - x;
|
||||
y1 = sprite->getMask()->y - y;
|
||||
x2 = sprite->getMask()->x + sprite->getMask()->w - 1 - x;
|
||||
y2 = sprite->getMask()->y + sprite->getMask()->h - 1 - y;
|
||||
x1 = document->getMask()->x - x;
|
||||
y1 = document->getMask()->y - y;
|
||||
x2 = document->getMask()->x + document->getMask()->w - 1 - x;
|
||||
y2 = document->getMask()->y + document->getMask()->h - 1 - y;
|
||||
|
||||
// clip
|
||||
x1 = MID(0, x1, image->w-1);
|
||||
|
@ -51,21 +51,22 @@ InvertMaskCommand::InvertMaskCommand()
|
||||
bool InvertMaskCommand::onEnabled(Context* context)
|
||||
{
|
||||
const ActiveDocumentReader document(context);
|
||||
return document != NULL && document->getSprite() != NULL;
|
||||
return
|
||||
document != NULL &&
|
||||
document->getSprite() != NULL;
|
||||
}
|
||||
|
||||
void InvertMaskCommand::onExecute(Context* context)
|
||||
{
|
||||
bool has_mask = false;
|
||||
bool hasMask = false;
|
||||
{
|
||||
const ActiveDocumentReader document(context);
|
||||
const Sprite* sprite(document->getSprite());
|
||||
if (sprite->getMask()->bitmap)
|
||||
has_mask = true;
|
||||
if (document->isMaskVisible())
|
||||
hasMask = true;
|
||||
}
|
||||
|
||||
// without mask?...
|
||||
if (!has_mask) {
|
||||
if (!hasMask) {
|
||||
// so we select all
|
||||
Command* mask_all_cmd =
|
||||
CommandsModule::instance()->getCommandByName(CommandId::MaskAll);
|
||||
@ -80,7 +81,7 @@ void InvertMaskCommand::onExecute(Context* context)
|
||||
/* undo */
|
||||
if (undo->isEnabled()) {
|
||||
undo->setLabel("Mask Invert");
|
||||
undo->undo_set_mask(sprite);
|
||||
undo->undo_set_mask(document);
|
||||
}
|
||||
|
||||
/* create a new mask */
|
||||
@ -91,23 +92,23 @@ void InvertMaskCommand::onExecute(Context* context)
|
||||
|
||||
/* remove in the new mask the current sprite marked region */
|
||||
image_rectfill(mask->bitmap,
|
||||
sprite->getMask()->x, sprite->getMask()->y,
|
||||
sprite->getMask()->x + sprite->getMask()->w-1,
|
||||
sprite->getMask()->y + sprite->getMask()->h-1, 0);
|
||||
document->getMask()->x, document->getMask()->y,
|
||||
document->getMask()->x + document->getMask()->w-1,
|
||||
document->getMask()->y + document->getMask()->h-1, 0);
|
||||
|
||||
/* invert the current mask in the sprite */
|
||||
mask_invert(sprite->getMask());
|
||||
if (sprite->getMask()->bitmap) {
|
||||
mask_invert(document->getMask());
|
||||
if (document->getMask()->bitmap) {
|
||||
/* copy the inverted region in the new mask */
|
||||
image_copy(mask->bitmap, sprite->getMask()->bitmap,
|
||||
sprite->getMask()->x, sprite->getMask()->y);
|
||||
image_copy(mask->bitmap, document->getMask()->bitmap,
|
||||
document->getMask()->x, document->getMask()->y);
|
||||
}
|
||||
|
||||
/* we need only need the area inside the sprite */
|
||||
mask_intersect(mask, 0, 0, sprite->getWidth(), sprite->getHeight());
|
||||
|
||||
/* set the new mask */
|
||||
sprite->setMask(mask);
|
||||
document->setMask(mask);
|
||||
mask_free(mask);
|
||||
|
||||
document->generateMaskBoundaries();
|
||||
|
@ -88,10 +88,10 @@ void LoadMaskCommand::onExecute(Context* context)
|
||||
// Add the mask change into the undo history.
|
||||
if (undo->isEnabled()) {
|
||||
undo->setLabel("Mask Load");
|
||||
undo->undo_set_mask(sprite);
|
||||
undo->undo_set_mask(document);
|
||||
}
|
||||
|
||||
sprite->setMask(mask);
|
||||
document->setMask(mask);
|
||||
mask_free(mask);
|
||||
|
||||
document->generateMaskBoundaries();
|
||||
|
@ -59,14 +59,15 @@ void MaskAllCommand::onExecute(Context* context)
|
||||
Sprite* sprite(document->getSprite());
|
||||
UndoHistory* undo(document->getUndoHistory());
|
||||
|
||||
/* undo */
|
||||
// Undo
|
||||
if (undo->isEnabled()) {
|
||||
undo->setLabel("Mask All");
|
||||
undo->undo_set_mask(sprite);
|
||||
undo->undo_set_mask(document);
|
||||
}
|
||||
|
||||
/* change the selection */
|
||||
mask_replace(sprite->getMask(), 0, 0, sprite->getWidth(), sprite->getHeight());
|
||||
// Change the selection
|
||||
mask_replace(document->getMask(), 0, 0, sprite->getWidth(), sprite->getHeight());
|
||||
document->setMaskVisible(true);
|
||||
|
||||
document->generateMaskBoundaries();
|
||||
update_screen_for_document(document);
|
||||
|
@ -53,8 +53,7 @@ bool MaskByColorCommand::onEnabled(Context* context)
|
||||
|
||||
void MaskByColorCommand::onExecute(Context* context)
|
||||
{
|
||||
ActiveDocumentWriter document(context);
|
||||
dialogs_mask_color(document);
|
||||
dialogs_mask_color(context->getActiveDocument());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -49,35 +49,30 @@ ReselectMaskCommand::ReselectMaskCommand()
|
||||
bool ReselectMaskCommand::onEnabled(Context* context)
|
||||
{
|
||||
const ActiveDocumentReader document(context);
|
||||
const Sprite* sprite(document ? document->getSprite(): 0);
|
||||
return
|
||||
sprite != NULL &&
|
||||
sprite->requestMask("*deselected*") != NULL;
|
||||
document && // The document does exist
|
||||
!document->isMaskVisible() && // The mask is hidden
|
||||
document->getMask() && // The mask does exist
|
||||
!document->getMask()->is_empty(); // But it is not empty
|
||||
}
|
||||
|
||||
void ReselectMaskCommand::onExecute(Context* context)
|
||||
{
|
||||
ActiveDocumentWriter document(context);
|
||||
Sprite* sprite(document->getSprite());
|
||||
UndoHistory* undo = document->getUndoHistory();
|
||||
|
||||
// Request *deselected* mask
|
||||
Mask* mask = sprite->requestMask("*deselected*");
|
||||
// TODO IMPLEMENT THIS Add an undo action in the history to reverse the change of a Document's int field
|
||||
|
||||
// Undo
|
||||
if (undo->isEnabled()) {
|
||||
undo->setLabel("Mask Reselection");
|
||||
undo->undo_set_mask(sprite);
|
||||
//undo->undo_set_mask(document);
|
||||
}
|
||||
|
||||
// Set the mask.
|
||||
sprite->setMask(mask);
|
||||
|
||||
// Remove the *deselected* mask.
|
||||
sprite->removeMask(mask);
|
||||
mask_free(mask);
|
||||
|
||||
// Make the mask visible again.
|
||||
document->setMaskVisible(true);
|
||||
document->generateMaskBoundaries();
|
||||
|
||||
update_screen_for_document(document);
|
||||
}
|
||||
|
||||
|
@ -124,30 +124,31 @@ protected:
|
||||
}
|
||||
|
||||
// rotate mask
|
||||
if (m_sprite->getMask()->bitmap) {
|
||||
if (m_document->isMaskVisible()) {
|
||||
Mask* origMask = m_document->getMask();
|
||||
Mask* new_mask = mask_new();
|
||||
int x = 0, y = 0;
|
||||
|
||||
switch (m_angle) {
|
||||
case 180:
|
||||
x = m_sprite->getWidth() - m_sprite->getMask()->x - m_sprite->getMask()->w;
|
||||
y = m_sprite->getHeight() - m_sprite->getMask()->y - m_sprite->getMask()->h;
|
||||
x = m_sprite->getWidth() - origMask->x - origMask->w;
|
||||
y = m_sprite->getHeight() - origMask->y - origMask->h;
|
||||
break;
|
||||
case 90:
|
||||
x = m_sprite->getHeight() - m_sprite->getMask()->y - m_sprite->getMask()->h;
|
||||
y = m_sprite->getMask()->x;
|
||||
x = m_sprite->getHeight() - origMask->y - origMask->h;
|
||||
y = origMask->x;
|
||||
break;
|
||||
case -90:
|
||||
x = m_sprite->getMask()->y;
|
||||
y = m_sprite->getWidth() - m_sprite->getMask()->x - m_sprite->getMask()->w;
|
||||
x = origMask->y;
|
||||
y = m_sprite->getWidth() - origMask->x - origMask->w;
|
||||
break;
|
||||
}
|
||||
|
||||
// create the new rotated mask
|
||||
mask_replace(new_mask, x, y,
|
||||
m_angle == 180 ? m_sprite->getMask()->w: m_sprite->getMask()->h,
|
||||
m_angle == 180 ? m_sprite->getMask()->h: m_sprite->getMask()->w);
|
||||
image_rotate(m_sprite->getMask()->bitmap, new_mask->bitmap, m_angle);
|
||||
m_angle == 180 ? origMask->w: origMask->h,
|
||||
m_angle == 180 ? origMask->h: origMask->w);
|
||||
image_rotate(origMask->bitmap, new_mask->bitmap, m_angle);
|
||||
|
||||
// copy new mask
|
||||
undoTransaction.copyToCurrentMask(new_mask);
|
||||
|
@ -52,18 +52,12 @@ SaveMaskCommand::SaveMaskCommand()
|
||||
bool SaveMaskCommand::onEnabled(Context* context)
|
||||
{
|
||||
const ActiveDocumentReader document(context);
|
||||
const Sprite* sprite(document ? document->getSprite(): NULL);
|
||||
if (!sprite)
|
||||
return false;
|
||||
else
|
||||
return (sprite->getMask() &&
|
||||
sprite->getMask()->bitmap) ? true: false;
|
||||
return document && document->isMaskVisible();
|
||||
}
|
||||
|
||||
void SaveMaskCommand::onExecute(Context* context)
|
||||
{
|
||||
const ActiveDocumentReader document(context);
|
||||
const Sprite* sprite(document ? document->getSprite(): NULL);
|
||||
base::string filename = "default.msk";
|
||||
int ret;
|
||||
|
||||
@ -91,7 +85,7 @@ void SaveMaskCommand::onExecute(Context* context)
|
||||
/* "no": we must back to select other file-name */
|
||||
}
|
||||
|
||||
if (save_msk_file(sprite->getMask(), filename.c_str()) != 0)
|
||||
if (save_msk_file(document->getMask(), filename.c_str()) != 0)
|
||||
Alert::show("Error<<Error saving .msk file<<%s||&Close", filename.c_str());
|
||||
}
|
||||
|
||||
|
@ -107,18 +107,18 @@ protected:
|
||||
return; // UndoTransaction destructor will undo all operations
|
||||
}
|
||||
|
||||
// resize mask
|
||||
if (m_sprite->getMask()->bitmap) {
|
||||
Image* old_bitmap = image_crop(m_sprite->getMask()->bitmap, -1, -1,
|
||||
m_sprite->getMask()->bitmap->w+2,
|
||||
m_sprite->getMask()->bitmap->h+2, 0);
|
||||
// Resize mask
|
||||
if (m_document->isMaskVisible()) {
|
||||
Image* old_bitmap = image_crop(m_document->getMask()->bitmap, -1, -1,
|
||||
m_document->getMask()->bitmap->w+2,
|
||||
m_document->getMask()->bitmap->h+2, 0);
|
||||
|
||||
int w = scale_x(old_bitmap->w);
|
||||
int h = scale_y(old_bitmap->h);
|
||||
Mask* new_mask = mask_new();
|
||||
mask_replace(new_mask,
|
||||
scale_x(m_sprite->getMask()->x-1),
|
||||
scale_y(m_sprite->getMask()->y-1), MAX(1, w), MAX(1, h));
|
||||
scale_x(m_document->getMask()->x-1),
|
||||
scale_y(m_document->getMask()->y-1), MAX(1, w), MAX(1, h));
|
||||
image_resize(old_bitmap, new_mask->bitmap,
|
||||
m_resize_method,
|
||||
m_sprite->getCurrentPalette(), // Ignored
|
||||
|
@ -102,7 +102,7 @@ void FilterManagerImpl::setTarget(int target)
|
||||
void FilterManagerImpl::begin()
|
||||
{
|
||||
m_row = 0;
|
||||
m_mask = m_sprite->getMask();
|
||||
m_mask = m_document->getMask();
|
||||
|
||||
updateMask(m_mask, m_src);
|
||||
}
|
||||
@ -114,8 +114,8 @@ void FilterManagerImpl::beginForPreview()
|
||||
m_preview_mask = NULL;
|
||||
}
|
||||
|
||||
if ((m_sprite->getMask()) && (m_sprite->getMask()->bitmap))
|
||||
m_preview_mask = mask_new_copy(m_sprite->getMask());
|
||||
if (m_document->isMaskVisible())
|
||||
m_preview_mask = mask_new_copy(m_document->getMask());
|
||||
else {
|
||||
m_preview_mask = mask_new();
|
||||
mask_replace(m_preview_mask,
|
||||
@ -340,7 +340,7 @@ void FilterManagerImpl::init(const Layer* layer, Image* image, int offset_x, int
|
||||
m_offset_x = offset_x;
|
||||
m_offset_y = offset_y;
|
||||
|
||||
if (!updateMask(m_sprite->getMask(), image))
|
||||
if (!updateMask(m_document->getMask(), image))
|
||||
throw InvalidAreaException();
|
||||
|
||||
if (m_preview_mask) {
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "app/color_utils.h"
|
||||
#include "base/bind.h"
|
||||
#include "core/cfg.h"
|
||||
#include "document.h"
|
||||
#include "document_wrappers.h"
|
||||
#include "gui/box.h"
|
||||
#include "gui/button.h"
|
||||
#include "gui/frame.h"
|
||||
@ -44,14 +46,15 @@ static ColorButton* button_color;
|
||||
static CheckBox* check_preview;
|
||||
static Slider* slider_tolerance;
|
||||
|
||||
static void button_1_command(JWidget widget);
|
||||
static void button_2_command(JWidget widget);
|
||||
static void button_1_command(Widget* widget, const DocumentReader& document);
|
||||
static void button_2_command(Widget* widget, const DocumentReader& document);
|
||||
|
||||
static Mask* gen_mask(const Sprite* sprite);
|
||||
static void mask_preview(Document* document);
|
||||
static void mask_preview(const DocumentReader& document);
|
||||
|
||||
void dialogs_mask_color(Document* document)
|
||||
{
|
||||
DocumentReader documentReader(document);
|
||||
Sprite* sprite = document->getSprite();
|
||||
Box* box1, *box2, *box3, *box4;
|
||||
Widget* label_color;
|
||||
@ -90,17 +93,14 @@ void dialogs_mask_color(Document* document)
|
||||
if (get_config_bool("MaskColor", "Preview", true))
|
||||
check_preview->setSelected(true);
|
||||
|
||||
button_1->user_data[1] = document;
|
||||
button_2->user_data[1] = document;
|
||||
|
||||
button_1->Click.connect(Bind<void>(&button_1_command, button_1));
|
||||
button_2->Click.connect(Bind<void>(&button_2_command, button_2));
|
||||
button_1->Click.connect(Bind<void>(&button_1_command, button_1, Ref(documentReader)));
|
||||
button_2->Click.connect(Bind<void>(&button_2_command, button_2, Ref(documentReader)));
|
||||
button_ok->Click.connect(Bind<void>(&Frame::closeWindow, window.get(), button_ok));
|
||||
button_cancel->Click.connect(Bind<void>(&Frame::closeWindow, window.get(), button_cancel));
|
||||
|
||||
button_color->Change.connect(Bind<void>(&mask_preview, document));
|
||||
slider_tolerance->Change.connect(Bind<void>(&mask_preview, document));
|
||||
check_preview->Click.connect(Bind<void>(&mask_preview, document));
|
||||
button_color->Change.connect(Bind<void>(&mask_preview, Ref(documentReader)));
|
||||
slider_tolerance->Change.connect(Bind<void>(&mask_preview, Ref(documentReader)));
|
||||
check_preview->Click.connect(Bind<void>(&mask_preview, Ref(documentReader)));
|
||||
|
||||
jwidget_magnetic(button_ok, true);
|
||||
jwidget_expansive(button_color, true);
|
||||
@ -118,7 +118,7 @@ void dialogs_mask_color(Document* document)
|
||||
window->center_window();
|
||||
|
||||
/* mask first preview */
|
||||
mask_preview(document);
|
||||
mask_preview(documentReader);
|
||||
|
||||
/* load window configuration */
|
||||
load_window_pos(window, "MaskColor");
|
||||
@ -127,18 +127,19 @@ void dialogs_mask_color(Document* document)
|
||||
window->open_window_fg();
|
||||
|
||||
if (window->get_killer() == button_ok) {
|
||||
DocumentWriter documentWriter(documentReader);
|
||||
UndoHistory* undo = document->getUndoHistory();
|
||||
Mask* mask;
|
||||
|
||||
/* undo */
|
||||
if (undo->isEnabled()) {
|
||||
undo->setLabel("Mask by Color");
|
||||
undo->undo_set_mask(sprite);
|
||||
undo->undo_set_mask(document);
|
||||
}
|
||||
|
||||
/* change the mask */
|
||||
mask = gen_mask(sprite);
|
||||
sprite->setMask(mask);
|
||||
document->setMask(mask);
|
||||
mask_free(mask);
|
||||
|
||||
set_config_color("MaskColor", "Color", button_color->getColor());
|
||||
@ -154,16 +155,16 @@ void dialogs_mask_color(Document* document)
|
||||
save_window_pos(window, "MaskColor");
|
||||
}
|
||||
|
||||
static void button_1_command(JWidget widget)
|
||||
static void button_1_command(Widget* widget, const DocumentReader& document)
|
||||
{
|
||||
button_color->setColor(app_get_colorbar()->getFgColor());
|
||||
mask_preview((Document*)widget->user_data[1]);
|
||||
mask_preview(document);
|
||||
}
|
||||
|
||||
static void button_2_command(JWidget widget)
|
||||
static void button_2_command(Widget* widget, const DocumentReader& document)
|
||||
{
|
||||
button_color->setColor(app_get_colorbar()->getBgColor());
|
||||
mask_preview((Document*)widget->user_data[1]);
|
||||
mask_preview(document);
|
||||
}
|
||||
|
||||
static Mask *gen_mask(const Sprite* sprite)
|
||||
@ -182,14 +183,16 @@ static Mask *gen_mask(const Sprite* sprite)
|
||||
return mask;
|
||||
}
|
||||
|
||||
static void mask_preview(Document* document)
|
||||
static void mask_preview(const DocumentReader& document)
|
||||
{
|
||||
if (check_preview->isSelected()) {
|
||||
Mask* mask = gen_mask(document->getSprite());
|
||||
|
||||
document->generateMaskBoundaries(mask);
|
||||
update_screen_for_document(document);
|
||||
|
||||
{
|
||||
DocumentWriter documentWriter(document);
|
||||
documentWriter->generateMaskBoundaries(mask);
|
||||
}
|
||||
mask_free(mask);
|
||||
|
||||
update_screen_for_document(document);
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,10 @@ Document::Document(Sprite* sprite)
|
||||
m_preferred.scroll_y = 0;
|
||||
m_preferred.zoom = 0;
|
||||
m_preferred.virgin = true;
|
||||
|
||||
// Mask
|
||||
m_mask = new Mask();
|
||||
m_maskVisible = true;
|
||||
}
|
||||
|
||||
Document::~Document()
|
||||
@ -70,6 +74,7 @@ Document::~Document()
|
||||
delete m_mutex;
|
||||
delete m_undoHistory;
|
||||
delete m_sprite;
|
||||
delete m_mask;
|
||||
}
|
||||
|
||||
Document* Document::createBasicDocument(int imgtype, int width, int height, int ncolors)
|
||||
@ -183,16 +188,20 @@ const _BoundSeg* Document::getBoundariesSegments() const
|
||||
|
||||
void Document::generateMaskBoundaries(Mask* mask)
|
||||
{
|
||||
// No mask specified? Use the current one in the document
|
||||
if (!mask)
|
||||
mask = m_sprite->getMask();
|
||||
|
||||
if (m_bound.seg) {
|
||||
base_free(m_bound.seg);
|
||||
m_bound.seg = NULL;
|
||||
m_bound.nseg = 0;
|
||||
}
|
||||
|
||||
// No mask specified? Use the current one in the document
|
||||
if (!mask) {
|
||||
if (!isMaskVisible()) // The mask is hidden
|
||||
return; // Done, without boundaries
|
||||
else
|
||||
mask = getMask(); // Use the document mask
|
||||
}
|
||||
|
||||
ASSERT(mask != NULL);
|
||||
|
||||
if (mask->bitmap) {
|
||||
@ -252,6 +261,36 @@ Image* Document::getExtraCelImage() const
|
||||
return m_extraImage;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Mask
|
||||
|
||||
Mask* Document::getMask() const
|
||||
{
|
||||
return m_mask;
|
||||
}
|
||||
|
||||
void Document::setMask(const Mask* mask)
|
||||
{
|
||||
if (m_mask)
|
||||
mask_free(m_mask);
|
||||
|
||||
m_mask = mask_new_copy(mask);
|
||||
m_maskVisible = true;
|
||||
}
|
||||
|
||||
bool Document::isMaskVisible() const
|
||||
{
|
||||
return
|
||||
m_maskVisible && // The mask was not hidden by the user explicitly
|
||||
m_mask && // The mask does exist
|
||||
!m_mask->is_empty(); // The mask is not empty
|
||||
}
|
||||
|
||||
void Document::setMaskVisible(bool visible)
|
||||
{
|
||||
m_maskVisible = visible;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Clonning
|
||||
|
||||
|
@ -110,6 +110,28 @@ public:
|
||||
Cel* getExtraCel() const;
|
||||
Image* getExtraCelImage() const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Mask
|
||||
|
||||
// Returns the current mask, it can be empty. The mask could be not
|
||||
// empty but hidden to the user if the setMaskVisible(false) was
|
||||
// used called before.
|
||||
Mask* getMask() const;
|
||||
|
||||
// Sets the current mask. The new mask will be visible by default,
|
||||
// so you don't need to call setMaskVisible(true).
|
||||
void setMask(const Mask* mask);
|
||||
|
||||
// Returns true only when the mask is not empty, and was not yet
|
||||
// hidden using setMaskVisible (e.g. when the user "deselect the
|
||||
// mask").
|
||||
bool isMaskVisible() const;
|
||||
|
||||
// Changes the visibility state of the mask (it is useful only if
|
||||
// the getMask() is not empty and the user can see that the mask is
|
||||
// being hidden and shown to him).
|
||||
void setMaskVisible(bool visible);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Clonning
|
||||
|
||||
@ -172,6 +194,10 @@ private:
|
||||
// Image of the extra cel.
|
||||
Image* m_extraImage;
|
||||
|
||||
// Current mask.
|
||||
Mask* m_mask;
|
||||
bool m_maskVisible;
|
||||
|
||||
DISABLE_COPYING(Document);
|
||||
};
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
#ifndef DOCUMENT_ID_H_INCLUDED
|
||||
#define DOCUMENT_ID_H_INCLUDED
|
||||
|
||||
typedef unsigned int DocumentId;
|
||||
typedef ase_uint32 DocumentId;
|
||||
|
||||
const DocumentId WithoutDocumentId = 0;
|
||||
|
||||
|
@ -118,9 +118,7 @@ class AseFormat : public FileFormat
|
||||
FILE_SUPPORT_INDEXED |
|
||||
FILE_SUPPORT_LAYERS |
|
||||
FILE_SUPPORT_FRAMES |
|
||||
FILE_SUPPORT_PALETTES |
|
||||
FILE_SUPPORT_MASKS_REPOSITORY |
|
||||
FILE_SUPPORT_PATHS_REPOSITORY;
|
||||
FILE_SUPPORT_PALETTES;
|
||||
}
|
||||
|
||||
bool onLoad(FileOp* fop);
|
||||
@ -250,7 +248,7 @@ bool AseFormat::onLoad(FileOp *fop)
|
||||
|
||||
mask = ase_file_read_mask_chunk(f);
|
||||
if (mask)
|
||||
sprite->addMask(mask);
|
||||
delete mask; // TODO add the mask in some place?
|
||||
else
|
||||
fop_error(fop, "Warning: error loading a mask chunk\n");
|
||||
|
||||
@ -334,11 +332,6 @@ bool AseFormat::onSave(FileOp *fop)
|
||||
/* write layer chunks */
|
||||
for (; it != end; ++it)
|
||||
ase_file_write_layers(f, *it);
|
||||
|
||||
// Write all masks.
|
||||
MasksList masks = sprite->getMasksRepository();
|
||||
for (MasksList::iterator it = masks.begin(); it != masks.end(); ++it)
|
||||
ase_file_write_mask_chunk(f, *it);
|
||||
}
|
||||
|
||||
/* write cel chunks */
|
||||
|
@ -307,32 +307,6 @@ FileOp* fop_to_save_document(Document* document)
|
||||
}
|
||||
}
|
||||
|
||||
// Repositories.
|
||||
MasksList masks = fop->document->getSprite()->getMasksRepository();
|
||||
if (!masks.empty()) {
|
||||
int count = 0;
|
||||
|
||||
for (MasksList::iterator it = masks.begin(); it != masks.end(); ++it) {
|
||||
Mask* mask = *it;
|
||||
|
||||
// Names starting with '*' are ignored
|
||||
if (mask->name && *mask->name == '*')
|
||||
continue;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
if ((count > 0) && !(fop->format->support(FILE_SUPPORT_MASKS_REPOSITORY))) {
|
||||
usprintf(buf+ustrlen(buf), "<<- Mask Repository");
|
||||
}
|
||||
}
|
||||
|
||||
if (!fop->document->getSprite()->getPathsRepository().empty()) {
|
||||
if (!(fop->format->support(FILE_SUPPORT_PATHS_REPOSITORY))) {
|
||||
usprintf(buf+ustrlen(buf), "<<- Path Repository");
|
||||
}
|
||||
}
|
||||
|
||||
/* show the confirmation alert */
|
||||
if (ugetc(buf)) {
|
||||
/* interative */
|
||||
|
@ -34,9 +34,7 @@
|
||||
#define FILE_SUPPORT_FRAMES 0x00000100
|
||||
#define FILE_SUPPORT_PALETTES 0x00000200
|
||||
#define FILE_SUPPORT_SEQUENCES 0x00000400
|
||||
#define FILE_SUPPORT_MASKS_REPOSITORY 0x00000800
|
||||
#define FILE_SUPPORT_PATHS_REPOSITORY 0x00001000
|
||||
#define FILE_SUPPORT_GET_FORMAT_OPTIONS 0x00002000
|
||||
#define FILE_SUPPORT_GET_FORMAT_OPTIONS 0x00000800
|
||||
|
||||
class FormatOptions;
|
||||
class FileFormat;
|
||||
|
@ -18,14 +18,14 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory.h"
|
||||
#include "base/remove_from_container.h"
|
||||
#include "file/format_options.h"
|
||||
#include "raster/raster.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4355)
|
||||
#endif
|
||||
@ -221,56 +221,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
Mask* getMask() const {
|
||||
return m_mask;
|
||||
}
|
||||
|
||||
void setMask(const Mask* mask) {
|
||||
if (m_mask)
|
||||
mask_free(m_mask);
|
||||
|
||||
m_mask = mask_new_copy(mask);
|
||||
}
|
||||
|
||||
void addMask(Mask* mask) {
|
||||
if (!mask->name) // You can't add masks to repository without name
|
||||
return;
|
||||
|
||||
if (requestMask(mask->name)) // You can't add a mask that already exists
|
||||
return;
|
||||
|
||||
// And add the new mask
|
||||
m_repository.masks.push_back(mask);
|
||||
}
|
||||
|
||||
void removeMask(Mask* mask) {
|
||||
// Remove the mask from the repository
|
||||
base::remove_from_container(m_repository.masks, mask);
|
||||
}
|
||||
|
||||
Mask* requestMask(const char* name) const;
|
||||
|
||||
MasksList getMasksRepository() {
|
||||
return m_repository.masks;
|
||||
}
|
||||
|
||||
void addPath(Path* path) {
|
||||
m_repository.paths.push_back(path);
|
||||
}
|
||||
|
||||
void removePath(Path* path) {
|
||||
base::remove_from_container(m_repository.paths, path);
|
||||
}
|
||||
|
||||
void setPath(const Path* path) {
|
||||
delete m_path;
|
||||
m_path = new Path(*path);
|
||||
}
|
||||
|
||||
PathsList getPathsRepository() {
|
||||
return m_repository.paths;
|
||||
}
|
||||
|
||||
void render(Image* image, int x, int y) const {
|
||||
image_rectfill(image, x, y, x+m_width-1, y+m_height-1, 0);
|
||||
layer_render(getFolder(), image, x, y, getCurrentFrame());
|
||||
@ -290,12 +240,6 @@ private:
|
||||
Stock* m_stock; // stock to get images
|
||||
LayerFolder* m_folder; // main folder of layers
|
||||
Layer* m_layer; // current layer
|
||||
Path* m_path; // working path
|
||||
Mask* m_mask; // selected mask region
|
||||
struct {
|
||||
PathsList paths; // paths
|
||||
MasksList masks; // masks
|
||||
} m_repository;
|
||||
|
||||
// Current rgb map
|
||||
RgbMap* m_rgbMap;
|
||||
@ -318,8 +262,6 @@ SpriteImpl::SpriteImpl(Sprite* sprite, int imgtype, int width, int height, int n
|
||||
m_stock = new Stock(imgtype);
|
||||
m_folder = new LayerFolder(m_self);
|
||||
m_layer = NULL;
|
||||
m_path = NULL;
|
||||
m_mask = mask_new();
|
||||
|
||||
// Generate palette
|
||||
Palette pal(0, ncolors);
|
||||
@ -361,22 +303,6 @@ SpriteImpl::~SpriteImpl()
|
||||
if (m_stock)
|
||||
delete m_stock;
|
||||
|
||||
// Destroy paths
|
||||
{
|
||||
PathsList::iterator end = m_repository.paths.end();
|
||||
PathsList::iterator it = m_repository.paths.begin();
|
||||
for (; it != end; ++it)
|
||||
delete *it; // path
|
||||
}
|
||||
|
||||
// Destroy masks
|
||||
{
|
||||
MasksList::iterator end = m_repository.masks.end();
|
||||
MasksList::iterator it = m_repository.masks.begin();
|
||||
for (; it != end; ++it)
|
||||
delete *it; // mask
|
||||
}
|
||||
|
||||
// Destroy palettes
|
||||
{
|
||||
PalettesList::iterator end = m_palettes.end();
|
||||
@ -385,8 +311,7 @@ SpriteImpl::~SpriteImpl()
|
||||
delete *it; // palette
|
||||
}
|
||||
|
||||
// Destroy undo, mask, etc.
|
||||
delete m_mask;
|
||||
// Destroy RGB map
|
||||
delete m_rgbMap;
|
||||
}
|
||||
|
||||
@ -431,20 +356,6 @@ void SpriteImpl::setTotalFrames(int frames)
|
||||
m_frames = frames;
|
||||
}
|
||||
|
||||
Mask *SpriteImpl::requestMask(const char *name) const
|
||||
{
|
||||
MasksList::const_iterator end = m_repository.masks.end();
|
||||
MasksList::const_iterator it = m_repository.masks.begin();
|
||||
|
||||
for (; it != end; ++it) {
|
||||
Mask* mask = *it;
|
||||
if (strcmp(mask->name, name) == 0)
|
||||
return mask;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int SpriteImpl::getPixel(int x, int y) const
|
||||
{
|
||||
int color = 0;
|
||||
@ -760,83 +671,6 @@ void Sprite::remapImages(int frame_from, int frame_to, const std::vector<int>& m
|
||||
m_impl->remapImages(frame_from, frame_to, mapping);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Mask
|
||||
|
||||
Mask* Sprite::getMask() const
|
||||
{
|
||||
return m_impl->getMask();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the current mask (makes a copy of "mask")
|
||||
*/
|
||||
void Sprite::setMask(const Mask* mask)
|
||||
{
|
||||
m_impl->setMask(mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a mask to the sprites's repository
|
||||
*/
|
||||
void Sprite::addMask(Mask* mask)
|
||||
{
|
||||
m_impl->addMask(mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a mask from the sprites's repository
|
||||
*/
|
||||
void Sprite::removeMask(Mask* mask)
|
||||
{
|
||||
m_impl->removeMask(mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a mask from the sprite's repository searching it by its name
|
||||
*/
|
||||
Mask* Sprite::requestMask(const char* name) const
|
||||
{
|
||||
return m_impl->requestMask(name);
|
||||
}
|
||||
|
||||
MasksList Sprite::getMasksRepository()
|
||||
{
|
||||
return m_impl->getMasksRepository();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Path
|
||||
|
||||
/**
|
||||
* Adds a path to the sprites's repository
|
||||
*/
|
||||
void Sprite::addPath(Path* path)
|
||||
{
|
||||
m_impl->addPath(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a path from the sprites's repository
|
||||
*/
|
||||
void Sprite::removePath(Path* path)
|
||||
{
|
||||
m_impl->removePath(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the current path (makes a copy of "path")
|
||||
*/
|
||||
void Sprite::setPath(const Path* path)
|
||||
{
|
||||
m_impl->setPath(path);
|
||||
}
|
||||
|
||||
PathsList Sprite::getPathsRepository()
|
||||
{
|
||||
return m_impl->getPathsRepository();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Drawing
|
||||
|
||||
|
@ -118,27 +118,6 @@ public:
|
||||
|
||||
void remapImages(int frame_from, int frame_to, const std::vector<int>& mapping);
|
||||
|
||||
////////////////////////////////////////
|
||||
// Mask
|
||||
|
||||
Mask* getMask() const;
|
||||
void setMask(const Mask* mask);
|
||||
|
||||
void addMask(Mask* mask);
|
||||
void removeMask(Mask* mask);
|
||||
Mask* requestMask(const char* name) const;
|
||||
|
||||
MasksList getMasksRepository();
|
||||
|
||||
////////////////////////////////////////
|
||||
// Path
|
||||
|
||||
void addPath(Path* path);
|
||||
void removePath(Path* path);
|
||||
void setPath(const Path* path);
|
||||
|
||||
PathsList getPathsRepository();
|
||||
|
||||
////////////////////////////////////////
|
||||
// Drawing
|
||||
|
||||
|
@ -18,14 +18,10 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <allegro/config.h>
|
||||
|
||||
#include "base/memory.h"
|
||||
#include "context.h"
|
||||
#include "document.h"
|
||||
#include "documents.h"
|
||||
#include "raster/cel.h"
|
||||
#include "raster/dirty.h"
|
||||
#include "raster/image.h"
|
||||
@ -35,14 +31,22 @@
|
||||
#include "raster/sprite.h"
|
||||
#include "raster/stock.h"
|
||||
#include "raster/undo_history.h"
|
||||
#include "ui_context.h"
|
||||
|
||||
/* undo state */
|
||||
#include <allegro/config.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <list>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
// Undo state
|
||||
enum {
|
||||
DO_UNDO,
|
||||
DO_REDO,
|
||||
};
|
||||
|
||||
// undo types
|
||||
// Undo types
|
||||
enum {
|
||||
// group
|
||||
UNDO_TYPE_OPEN,
|
||||
@ -78,7 +82,7 @@ enum {
|
||||
UNDO_TYPE_SET_PALETTE_COLORS,
|
||||
UNDO_TYPE_REMAP_PALETTE,
|
||||
|
||||
/* misc */
|
||||
// misc
|
||||
UNDO_TYPE_SET_MASK,
|
||||
UNDO_TYPE_SET_IMGTYPE,
|
||||
UNDO_TYPE_SET_SIZE,
|
||||
@ -135,7 +139,7 @@ struct UndoAction
|
||||
static int count_undo_groups(UndoStream* undo_stream);
|
||||
static bool out_of_group(UndoStream* undo_stream);
|
||||
|
||||
/* Undo actions */
|
||||
// Undo actions
|
||||
|
||||
static void chunk_open_new(UndoStream* stream);
|
||||
static void chunk_open_invert(UndoStream* stream, UndoChunk* chunk);
|
||||
@ -197,7 +201,7 @@ static void chunk_set_palette_colors_invert(UndoStream* stream, UndoChunkSetPale
|
||||
static void chunk_remap_palette_new(UndoStream* stream, Sprite* sprite, int frame_from, int frame_to, const std::vector<int>& mapping);
|
||||
static void chunk_remap_palette_invert(UndoStream* stream, UndoChunkRemapPalette *chunk);
|
||||
|
||||
static void chunk_set_mask_new(UndoStream* stream, Sprite *sprite);
|
||||
static void chunk_set_mask_new(UndoStream* stream, Document* document);
|
||||
static void chunk_set_mask_invert(UndoStream* stream, UndoChunkSetMask* chunk);
|
||||
|
||||
static void chunk_set_imgtype_new(UndoStream* stream, Sprite *sprite);
|
||||
@ -218,7 +222,7 @@ static void chunk_set_frlen_invert(UndoStream* stream, UndoChunkSetFrlen *chunk)
|
||||
#define DECL_UNDO_ACTION(name) \
|
||||
{ #name, (void (*)(UndoStream* , UndoChunk*))chunk_##name##_invert }
|
||||
|
||||
/* warning: in the same order as in UNDO_TYPEs */
|
||||
// WARNING: in the same order as in UNDO_TYPEs
|
||||
static UndoAction undo_actions[] = {
|
||||
DECL_UNDO_ACTION(open),
|
||||
DECL_UNDO_ACTION(close),
|
||||
@ -248,7 +252,7 @@ static UndoAction undo_actions[] = {
|
||||
DECL_UNDO_ACTION(set_frlen),
|
||||
};
|
||||
|
||||
/* Raw data */
|
||||
// Raw data
|
||||
|
||||
static Dirty *read_raw_dirty(ase_uint8* raw_data);
|
||||
static ase_uint8* write_raw_dirty(ase_uint8* raw_data, Dirty* dirty);
|
||||
@ -1643,7 +1647,7 @@ static void chunk_remap_palette_invert(UndoStream* stream, UndoChunkRemapPalette
|
||||
|
||||
"set_mask"
|
||||
|
||||
DWORD sprite ID
|
||||
DWORD document ID
|
||||
MASK_DATA see read/write_raw_mask
|
||||
|
||||
***********************************************************************/
|
||||
@ -1651,37 +1655,37 @@ static void chunk_remap_palette_invert(UndoStream* stream, UndoChunkRemapPalette
|
||||
struct UndoChunkSetMask
|
||||
{
|
||||
UndoChunk head;
|
||||
ase_uint32 sprite_id;
|
||||
ase_uint32 doc_id;
|
||||
ase_uint8 data[0];
|
||||
};
|
||||
|
||||
void UndoHistory::undo_set_mask(Sprite *sprite)
|
||||
void UndoHistory::undo_set_mask(Document* document)
|
||||
{
|
||||
chunk_set_mask_new(m_undoStream, sprite);
|
||||
chunk_set_mask_new(m_undoStream, document);
|
||||
updateUndo();
|
||||
}
|
||||
|
||||
static void chunk_set_mask_new(UndoStream* stream, Sprite *sprite)
|
||||
static void chunk_set_mask_new(UndoStream* stream, Document* document)
|
||||
{
|
||||
UndoChunkSetMask* chunk = (UndoChunkSetMask* )
|
||||
UndoChunkSetMask* chunk = (UndoChunkSetMask*)
|
||||
undo_chunk_new(stream,
|
||||
UNDO_TYPE_SET_MASK,
|
||||
sizeof(UndoChunkSetMask)+get_raw_mask_size(sprite->getMask()));
|
||||
sizeof(UndoChunkSetMask)+get_raw_mask_size(document->getMask()));
|
||||
|
||||
chunk->sprite_id = sprite->getId();
|
||||
write_raw_mask(chunk->data, sprite->getMask());
|
||||
chunk->doc_id = document->getId();
|
||||
write_raw_mask(chunk->data, document->getMask());
|
||||
}
|
||||
|
||||
static void chunk_set_mask_invert(UndoStream* stream, UndoChunkSetMask* chunk)
|
||||
{
|
||||
Sprite *sprite = (Sprite *)GfxObj::find(chunk->sprite_id);
|
||||
Document* document = UIContext::instance()->getDocuments().getById(chunk->doc_id);
|
||||
ASSERT(document != NULL);
|
||||
|
||||
if (sprite) {
|
||||
if (document != NULL) {
|
||||
Mask* mask = read_raw_mask(chunk->data);
|
||||
|
||||
chunk_set_mask_new(stream, sprite);
|
||||
mask_copy(sprite->getMask(), mask);
|
||||
|
||||
chunk_set_mask_new(stream, document);
|
||||
mask_copy(document->getMask(), mask);
|
||||
mask_free(mask);
|
||||
}
|
||||
}
|
||||
|
@ -19,13 +19,14 @@
|
||||
#ifndef RASTER_UNDO_H_INCLUDED
|
||||
#define RASTER_UNDO_H_INCLUDED
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/exception.h"
|
||||
#include "raster/gfxobj.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class Cel;
|
||||
class Dirty;
|
||||
class Document;
|
||||
class Image;
|
||||
class Layer;
|
||||
class Mask;
|
||||
@ -87,7 +88,7 @@ public:
|
||||
void undo_set_palette_colors(Sprite* sprite, Palette* palette, int from, int to);
|
||||
void undo_remap_palette(Sprite* sprite, int frame_from, int frame_to,
|
||||
const std::vector<int>& mapping);
|
||||
void undo_set_mask(Sprite* sprite);
|
||||
void undo_set_mask(Document* document);
|
||||
void undo_set_imgtype(Sprite* sprite);
|
||||
void undo_set_size(Sprite* sprite);
|
||||
void undo_set_frame(Sprite* sprite);
|
||||
|
@ -33,8 +33,8 @@
|
||||
addresses_define \
|
||||
register int x; \
|
||||
\
|
||||
/* with mask */ \
|
||||
if (!loop->getMask()->is_empty()) { \
|
||||
/* Use mask */ \
|
||||
if (loop->useMask()) { \
|
||||
Point maskOrigin(loop->getMaskOrigin()); \
|
||||
\
|
||||
if ((y < maskOrigin.y) || (y >= maskOrigin.y+loop->getMask()->h)) \
|
||||
|
@ -260,13 +260,14 @@ public:
|
||||
|
||||
if (state) {
|
||||
if (loop->getDocument()->getUndoHistory()->isEnabled())
|
||||
loop->getDocument()->getUndoHistory()->undo_set_mask(loop->getSprite());
|
||||
loop->getDocument()->getUndoHistory()->undo_set_mask(loop->getDocument());
|
||||
|
||||
loop->getMask()->freeze();
|
||||
loop->getMask()->reserve(0, 0, loop->getSprite()->getWidth(), loop->getSprite()->getHeight());
|
||||
}
|
||||
else {
|
||||
loop->getMask()->unfreeze();
|
||||
loop->getDocument()->setMaskVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,6 +251,9 @@ public:
|
||||
// Should return an image where we can write pixels
|
||||
virtual Image* getDstImage() = 0;
|
||||
|
||||
// Returns true if we should use the mask to limit the paint area.
|
||||
virtual bool useMask() = 0;
|
||||
|
||||
// Current mask to limit paint area
|
||||
virtual Mask* getMask() = 0;
|
||||
|
||||
|
@ -131,8 +131,8 @@ void UndoTransaction::cropSprite(int x, int y, int w, int h, int bgcolor)
|
||||
if (background_layer)
|
||||
cropLayer(background_layer, 0, 0, m_sprite->getWidth(), m_sprite->getHeight(), bgcolor);
|
||||
|
||||
if (!m_sprite->getMask()->is_empty())
|
||||
setMaskPosition(m_sprite->getMask()->x-x, m_sprite->getMask()->y-y);
|
||||
if (!m_document->getMask()->is_empty())
|
||||
setMaskPosition(m_document->getMask()->x-x, m_document->getMask()->y-y);
|
||||
}
|
||||
|
||||
void UndoTransaction::autocropSprite(int bgcolor)
|
||||
@ -921,9 +921,11 @@ void UndoTransaction::clearMask(int bgcolor)
|
||||
if (!image)
|
||||
return;
|
||||
|
||||
Mask* mask = m_document->getMask();
|
||||
|
||||
// if the mask is empty then we have to clear the entire image
|
||||
// in the cel
|
||||
if (m_sprite->getMask()->is_empty()) {
|
||||
if (mask->is_empty()) {
|
||||
// if the layer is the background then we clear the image
|
||||
if (m_sprite->getCurrentLayer()->is_background()) {
|
||||
if (isEnabled())
|
||||
@ -939,13 +941,13 @@ void UndoTransaction::clearMask(int bgcolor)
|
||||
}
|
||||
}
|
||||
else {
|
||||
int offset_x = m_sprite->getMask()->x-cel->x;
|
||||
int offset_y = m_sprite->getMask()->y-cel->y;
|
||||
int offset_x = mask->x-cel->x;
|
||||
int offset_y = mask->y-cel->y;
|
||||
int u, v, putx, puty;
|
||||
int x1 = MAX(0, offset_x);
|
||||
int y1 = MAX(0, offset_y);
|
||||
int x2 = MIN(image->w-1, offset_x+m_sprite->getMask()->w-1);
|
||||
int y2 = MIN(image->h-1, offset_y+m_sprite->getMask()->h-1);
|
||||
int x2 = MIN(image->w-1, offset_x+mask->w-1);
|
||||
int y2 = MIN(image->h-1, offset_y+mask->h-1);
|
||||
|
||||
// do nothing
|
||||
if (x1 > x2 || y1 > y2)
|
||||
@ -955,11 +957,11 @@ void UndoTransaction::clearMask(int bgcolor)
|
||||
m_undoHistory->undo_image(image, x1, y1, x2-x1+1, y2-y1+1);
|
||||
|
||||
// clear the masked zones
|
||||
for (v=0; v<m_sprite->getMask()->h; v++) {
|
||||
for (v=0; v<mask->h; v++) {
|
||||
div_t d = div(0, 8);
|
||||
ase_uint8* address = ((ase_uint8 **)m_sprite->getMask()->bitmap->line)[v]+d.quot;
|
||||
ase_uint8* address = ((ase_uint8 **)mask->bitmap->line)[v]+d.quot;
|
||||
|
||||
for (u=0; u<m_sprite->getMask()->w; u++) {
|
||||
for (u=0; u<mask->w; u++) {
|
||||
if ((*address & (1<<d.rem))) {
|
||||
putx = u + offset_x;
|
||||
puty = v + offset_y;
|
||||
@ -1019,45 +1021,33 @@ void UndoTransaction::pasteImage(const Image* src_image, int x, int y, int opaci
|
||||
|
||||
void UndoTransaction::copyToCurrentMask(Mask* mask)
|
||||
{
|
||||
ASSERT(m_sprite->getMask());
|
||||
ASSERT(m_document->getMask());
|
||||
ASSERT(mask);
|
||||
|
||||
if (isEnabled())
|
||||
m_undoHistory->undo_set_mask(m_sprite);
|
||||
m_undoHistory->undo_set_mask(m_document);
|
||||
|
||||
mask_copy(m_sprite->getMask(), mask);
|
||||
mask_copy(m_document->getMask(), mask);
|
||||
}
|
||||
|
||||
void UndoTransaction::setMaskPosition(int x, int y)
|
||||
{
|
||||
ASSERT(m_sprite->getMask());
|
||||
ASSERT(m_document->getMask());
|
||||
|
||||
if (isEnabled()) {
|
||||
m_undoHistory->undo_int(m_sprite->getMask(), &m_sprite->getMask()->x);
|
||||
m_undoHistory->undo_int(m_sprite->getMask(), &m_sprite->getMask()->y);
|
||||
m_undoHistory->undo_int(m_document->getMask(), &m_document->getMask()->x);
|
||||
m_undoHistory->undo_int(m_document->getMask(), &m_document->getMask()->y);
|
||||
}
|
||||
|
||||
m_sprite->getMask()->x = x;
|
||||
m_sprite->getMask()->y = y;
|
||||
m_document->getMask()->x = x;
|
||||
m_document->getMask()->y = y;
|
||||
}
|
||||
|
||||
void UndoTransaction::deselectMask()
|
||||
{
|
||||
// Destroy the *deselected* mask
|
||||
Mask* mask = m_sprite->requestMask("*deselected*");
|
||||
if (mask) {
|
||||
m_sprite->removeMask(mask);
|
||||
mask_free(mask);
|
||||
}
|
||||
// TODO IMPLEMENT THIS (add support to save values in UndoHistory from any object)
|
||||
// if (isEnabled())
|
||||
// m_undoHistory->undo_int(m_document);
|
||||
|
||||
// Save the selection in the repository
|
||||
mask = mask_new_copy(m_sprite->getMask());
|
||||
mask_set_name(mask, "*deselected*");
|
||||
m_sprite->addMask(mask);
|
||||
|
||||
if (isEnabled())
|
||||
m_undoHistory->undo_set_mask(m_sprite);
|
||||
|
||||
/// Deselect the mask
|
||||
mask_none(m_sprite->getMask());
|
||||
m_document->setMaskVisible(false);
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ enum {
|
||||
};
|
||||
|
||||
static void set_clipboard(Image* image, Palette* palette, bool set_system_clipboard);
|
||||
static bool copy_from_sprite(const Sprite* sprite);
|
||||
static bool copy_from_document(const Document* document);
|
||||
|
||||
static bool interactive_transform(Editor* widget, Image *dest_image, Image *image,
|
||||
int x, int y, int xout[4], int yout[4]);
|
||||
@ -129,14 +129,16 @@ static void set_clipboard(Image* image, Palette* palette, bool set_system_clipbo
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool copy_from_sprite(const Sprite* sprite)
|
||||
static bool copy_from_document(const Document* document)
|
||||
{
|
||||
ASSERT(sprite != NULL);
|
||||
Image* image = NewImageFromMask(sprite);
|
||||
ASSERT(document != NULL);
|
||||
ASSERT(document->isMaskVisible());
|
||||
|
||||
Image* image = NewImageFromMask(document);
|
||||
if (!image)
|
||||
return false;
|
||||
|
||||
const Palette* pal = sprite->getPalette(sprite->getCurrentFrame());
|
||||
const Palette* pal = document->getSprite()->getPalette(document->getSprite()->getCurrentFrame());
|
||||
set_clipboard(image, pal ? new Palette(*pal): NULL, true);
|
||||
return true;
|
||||
}
|
||||
@ -156,14 +158,14 @@ void clipboard::cut(DocumentWriter& document)
|
||||
ASSERT(document->getSprite() != NULL);
|
||||
ASSERT(document->getSprite()->getCurrentLayer() != NULL);
|
||||
|
||||
Sprite* sprite = document->getSprite();
|
||||
|
||||
if (!copy_from_sprite(sprite)) {
|
||||
if (!copy_from_document(document)) {
|
||||
Console console;
|
||||
console.printf("Can't copying an image portion from the current layer\n");
|
||||
}
|
||||
else {
|
||||
{
|
||||
Sprite* sprite = document->getSprite();
|
||||
|
||||
UndoTransaction undoTransaction(document, "Cut");
|
||||
undoTransaction.clearMask(app_get_color_to_clear_layer(sprite->getCurrentLayer()));
|
||||
undoTransaction.deselectMask();
|
||||
@ -178,7 +180,7 @@ void clipboard::copy(const DocumentReader& document)
|
||||
{
|
||||
ASSERT(document != NULL);
|
||||
|
||||
if (!copy_from_sprite(document->getSprite())) {
|
||||
if (!copy_from_document(document)) {
|
||||
Console console;
|
||||
console.printf("Can't copying an image portion from the current layer\n");
|
||||
}
|
||||
|
@ -36,37 +36,37 @@
|
||||
#include "widgets/editor.h"
|
||||
#include "widgets/statebar.h"
|
||||
|
||||
Image* NewImageFromMask(const Sprite* src_sprite)
|
||||
Image* NewImageFromMask(const Document* srcDocument)
|
||||
{
|
||||
const Sprite* srcSprite = srcDocument->getSprite();
|
||||
const Mask* srcMask = srcDocument->getMask();
|
||||
const ase_uint8* address;
|
||||
int x, y, u, v, getx, gety;
|
||||
Image *dst;
|
||||
const Image *src = src_sprite->getCurrentImage(&x, &y);
|
||||
const Image *src = srcSprite->getCurrentImage(&x, &y);
|
||||
div_t d;
|
||||
|
||||
ASSERT(src_sprite);
|
||||
ASSERT(src_sprite->getMask());
|
||||
ASSERT(src_sprite->getMask()->bitmap);
|
||||
ASSERT(srcSprite);
|
||||
ASSERT(srcMask);
|
||||
ASSERT(srcMask->bitmap);
|
||||
ASSERT(src);
|
||||
|
||||
dst = image_new(src_sprite->getImgType(),
|
||||
src_sprite->getMask()->w,
|
||||
src_sprite->getMask()->h);
|
||||
dst = image_new(srcSprite->getImgType(), srcMask->w, srcMask->h);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
/* clear the new image */
|
||||
// Clear the new image
|
||||
image_clear(dst, 0);
|
||||
|
||||
/* copy the masked zones */
|
||||
for (v=0; v<src_sprite->getMask()->h; v++) {
|
||||
// Copy the masked zones
|
||||
for (v=0; v<srcMask->h; v++) {
|
||||
d = div(0, 8);
|
||||
address = ((const ase_uint8 **)src_sprite->getMask()->bitmap->line)[v]+d.quot;
|
||||
address = ((const ase_uint8 **)srcMask->bitmap->line)[v]+d.quot;
|
||||
|
||||
for (u=0; u<src_sprite->getMask()->w; u++) {
|
||||
for (u=0; u<srcMask->w; u++) {
|
||||
if ((*address & (1<<d.rem))) {
|
||||
getx = u+src_sprite->getMask()->x-x;
|
||||
gety = v+src_sprite->getMask()->y-y;
|
||||
getx = u+srcMask->x-x;
|
||||
gety = v+srcMask->y-y;
|
||||
|
||||
if ((getx >= 0) && (getx < src->w) &&
|
||||
(gety >= 0) && (gety < src->h))
|
||||
@ -80,8 +80,8 @@ Image* NewImageFromMask(const Sprite* src_sprite)
|
||||
return dst;
|
||||
}
|
||||
|
||||
/* Gives to the user the possibility to move the sprite's layer in the
|
||||
current editor, returns true if the position was changed. */
|
||||
// Gives to the user the possibility to move the sprite's layer in the
|
||||
// current editor, returns true if the position was changed.
|
||||
int interactive_move_layer(int mode, bool use_undo, int (*callback)())
|
||||
{
|
||||
Editor* editor = current_editor;
|
||||
|
@ -23,9 +23,9 @@
|
||||
#include "widgets/editor.h" // For movement modes
|
||||
|
||||
class Image;
|
||||
class Sprite;
|
||||
class Document;
|
||||
|
||||
Image* NewImageFromMask(const Sprite* src);
|
||||
Image* NewImageFromMask(const Document* srcDocument);
|
||||
|
||||
int interactive_move_layer(int mode, bool use_undo, int (*callback)());
|
||||
|
||||
|
@ -617,11 +617,12 @@ void Editor::turnOnSelectionModifiers()
|
||||
{
|
||||
deleteDecorators();
|
||||
|
||||
Mask* mask = m_document->getMask();
|
||||
int x1, y1, x2, y2;
|
||||
|
||||
editor_to_screen(m_sprite->getMask()->x, m_sprite->getMask()->y, &x1, &y1);
|
||||
editor_to_screen(m_sprite->getMask()->x+m_sprite->getMask()->w-1,
|
||||
m_sprite->getMask()->y+m_sprite->getMask()->h-1, &x2, &y2);
|
||||
editor_to_screen(mask->x, mask->y, &x1, &y1);
|
||||
editor_to_screen(mask->x+mask->w-1,
|
||||
mask->y+mask->h-1, &x2, &y2);
|
||||
|
||||
addDecorator(new Decorator(Decorator::SELECTION_NW, Rect(x1-8, y1-8, 8, 8)));
|
||||
addDecorator(new Decorator(Decorator::SELECTION_N, Rect((x1+x2)/2-4, y1-8, 8, 8)));
|
||||
@ -769,7 +770,7 @@ void Editor::editor_update_statusbar_for_standby()
|
||||
}
|
||||
// For other tools
|
||||
else {
|
||||
Mask* mask = m_sprite->getMask();
|
||||
Mask* mask = m_document->getMask();
|
||||
|
||||
app_get_statusbar()->setStatusText
|
||||
(0, "Pos %d %d, Size %d %d, Frame %d",
|
||||
@ -1100,9 +1101,9 @@ bool Editor::onProcessMessage(JMessage msg)
|
||||
}
|
||||
|
||||
// Copy the mask to the extra cel image
|
||||
Image* tmpImage = NewImageFromMask(m_sprite);
|
||||
x = m_sprite->getMask()->x;
|
||||
y = m_sprite->getMask()->y;
|
||||
Image* tmpImage = NewImageFromMask(m_document);
|
||||
x = m_document->getMask()->x;
|
||||
y = m_document->getMask()->y;
|
||||
m_pixelsMovement = new PixelsMovement(m_document, m_sprite, tmpImage, x, y, opacity);
|
||||
delete tmpImage;
|
||||
|
||||
@ -1564,7 +1565,8 @@ void Editor::editor_setcursor(int x, int y)
|
||||
|
||||
// Move selection
|
||||
if (m_pixelsMovement->isDragging() ||
|
||||
m_sprite->getMask()->contains_point(x, y)) {
|
||||
m_document->isMaskVisible() &&
|
||||
m_document->getMask()->contains_point(x, y)) {
|
||||
hide_drawing_cursor();
|
||||
jmouse_set_cursor(JI_CURSOR_MOVE);
|
||||
|
||||
@ -1595,7 +1597,8 @@ void Editor::editor_setcursor(int x, int y)
|
||||
screen_to_editor(jmouse_x(0), jmouse_y(0), &x, &y);
|
||||
|
||||
// Move pixels
|
||||
if (m_sprite->getMask()->contains_point(x, y)) {
|
||||
if (m_document->isMaskVisible() &&
|
||||
m_document->getMask()->contains_point(x, y)) {
|
||||
hide_drawing_cursor();
|
||||
if (key[KEY_LCONTROL] ||
|
||||
key[KEY_RCONTROL]) // TODO configurable keys
|
||||
@ -1760,6 +1763,7 @@ class ToolLoopImpl : public IToolLoop
|
||||
TiledMode m_tiled_mode;
|
||||
Image* m_src_image;
|
||||
Image* m_dst_image;
|
||||
bool m_useMask;
|
||||
Mask* m_mask;
|
||||
Point m_maskOrigin;
|
||||
int m_opacity;
|
||||
@ -1779,21 +1783,20 @@ public:
|
||||
Sprite* sprite,
|
||||
Layer* layer,
|
||||
int button, const Color& primary_color, const Color& secondary_color)
|
||||
: m_editor(editor)
|
||||
, m_context(context)
|
||||
, m_tool(tool)
|
||||
, m_document(document)
|
||||
, m_sprite(sprite)
|
||||
, m_layer(layer)
|
||||
, m_cel(NULL)
|
||||
, m_cel_image(NULL)
|
||||
, m_cel_created(false)
|
||||
, m_canceled(false)
|
||||
, m_button(button)
|
||||
, m_primary_color(color_utils::color_for_layer(primary_color, layer))
|
||||
, m_secondary_color(color_utils::color_for_layer(secondary_color, layer))
|
||||
{
|
||||
m_editor = editor;
|
||||
m_context = context;
|
||||
m_tool = tool;
|
||||
m_document = document;
|
||||
m_sprite = sprite;
|
||||
m_layer = layer;
|
||||
m_cel = NULL;
|
||||
m_cel_image = NULL;
|
||||
m_cel_created = false;
|
||||
m_canceled = false;
|
||||
m_button = button;
|
||||
m_primary_color = color_utils::color_for_layer(primary_color, layer);
|
||||
m_secondary_color = color_utils::color_for_layer(secondary_color, layer);
|
||||
|
||||
// Settings
|
||||
ISettings* settings = m_context->getSettings();
|
||||
|
||||
@ -1871,7 +1874,15 @@ public:
|
||||
m_cel_image->mask_color);
|
||||
m_dst_image = image_new_copy(m_src_image);
|
||||
|
||||
m_mask = m_sprite->getMask();
|
||||
m_useMask = m_document->isMaskVisible();
|
||||
|
||||
// Selection ink
|
||||
if (getInk()->isSelection() && !m_document->isMaskVisible()) {
|
||||
Mask emptyMask;
|
||||
m_document->setMask(&emptyMask);
|
||||
}
|
||||
|
||||
m_mask = m_document->getMask();
|
||||
m_maskOrigin = (!m_mask->is_empty() ? Point(m_mask->x-x1, m_mask->y-y1):
|
||||
Point(0, 0));
|
||||
|
||||
@ -2015,6 +2026,7 @@ public:
|
||||
Layer* getLayer() { return m_layer; }
|
||||
Image* getSrcImage() { return m_src_image; }
|
||||
Image* getDstImage() { return m_dst_image; }
|
||||
bool useMask() { return m_useMask; }
|
||||
Mask* getMask() { return m_mask; }
|
||||
Point getMaskOrigin() { return m_maskOrigin; }
|
||||
int getMouseButton() { return m_button; }
|
||||
|
@ -148,8 +148,8 @@ public:
|
||||
m_undoTransaction.setMaskPosition(cel->x, cel->y);
|
||||
}
|
||||
else {
|
||||
m_sprite->getMask()->x = cel->x;
|
||||
m_sprite->getMask()->y = cel->y;
|
||||
m_documentWriter->getMask()->x = cel->x;
|
||||
m_documentWriter->getMask()->y = cel->y;
|
||||
}
|
||||
m_documentWriter->generateMaskBoundaries();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user