mirror of
https://github.com/aseprite/aseprite.git
synced 2025-04-02 13:20:12 +00:00
178 lines
5.6 KiB
C++
178 lines
5.6 KiB
C++
/* Aseprite
|
|
* Copyright (C) 2001-2013 David Capello
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "app/commands/cmd_flip.h"
|
|
|
|
#include "app/app.h"
|
|
#include "app/commands/params.h"
|
|
#include "app/context_access.h"
|
|
#include "app/document_api.h"
|
|
#include "app/modules/gui.h"
|
|
#include "app/undo_transaction.h"
|
|
#include "gfx/size.h"
|
|
#include "raster/algorithm/flip_image.h"
|
|
#include "raster/cel.h"
|
|
#include "raster/image.h"
|
|
#include "raster/mask.h"
|
|
#include "raster/sprite.h"
|
|
#include "raster/stock.h"
|
|
|
|
namespace app {
|
|
|
|
FlipCommand::FlipCommand()
|
|
: Command("Flip",
|
|
"Flip",
|
|
CmdRecordableFlag)
|
|
{
|
|
m_flipMask = false;
|
|
m_flipType = raster::algorithm::FlipHorizontal;
|
|
}
|
|
|
|
void FlipCommand::onLoadParams(Params* params)
|
|
{
|
|
std::string target = params->get("target");
|
|
m_flipMask = (target == "mask");
|
|
|
|
std::string orientation = params->get("orientation");
|
|
m_flipType = (orientation == "vertical" ? raster::algorithm::FlipVertical:
|
|
raster::algorithm::FlipHorizontal);
|
|
}
|
|
|
|
bool FlipCommand::onEnabled(Context* context)
|
|
{
|
|
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable);
|
|
}
|
|
|
|
void FlipCommand::onExecute(Context* context)
|
|
{
|
|
ContextWriter writer(context);
|
|
Document* document = writer.document();
|
|
Sprite* sprite = writer.sprite();
|
|
DocumentApi api = document->getApi();
|
|
|
|
{
|
|
UndoTransaction undoTransaction(writer.context(),
|
|
m_flipMask ?
|
|
(m_flipType == raster::algorithm::FlipHorizontal ?
|
|
"Flip Horizontal":
|
|
"Flip Vertical"):
|
|
(m_flipType == raster::algorithm::FlipHorizontal ?
|
|
"Flip Canvas Horizontal":
|
|
"Flip Canvas Vertical"));
|
|
|
|
if (m_flipMask) {
|
|
int x, y;
|
|
Image* image = writer.image(&x, &y);
|
|
if (!image)
|
|
return;
|
|
|
|
Mask* mask = NULL;
|
|
bool alreadyFlipped = false;
|
|
|
|
// This variable will be the area to be flipped inside the image.
|
|
gfx::Rect bounds(gfx::Point(0, 0),
|
|
gfx::Size(image->w, image->h));
|
|
|
|
// If there is some portion of sprite selected, we flip the
|
|
// selected region only. If the mask isn't visible, we flip the
|
|
// whole image.
|
|
if (document->isMaskVisible()) {
|
|
mask = document->getMask();
|
|
gfx::Rect maskBounds = mask->getBounds();
|
|
|
|
// Adjust the mask depending on the cel position.
|
|
maskBounds.offset(-x, -y);
|
|
|
|
// Intersect the full area of the image with the mask's
|
|
// bounds, so we don't request to flip an area outside the
|
|
// image's bounds.
|
|
bounds = bounds.createIntersect(maskBounds);
|
|
|
|
// If the mask isn't a rectangular area, we've to flip the mask too.
|
|
if (mask->getBitmap() != NULL && !mask->isRectangular()) {
|
|
int bgcolor = app_get_color_to_clear_layer(writer.layer());
|
|
|
|
// Flip the portion of image specified by the mask.
|
|
api.flipImageWithMask(image, mask, m_flipType, bgcolor);
|
|
alreadyFlipped = true;
|
|
|
|
// Flip the mask.
|
|
Image* maskBitmap = mask->getBitmap();
|
|
if (maskBitmap != NULL) {
|
|
// Create a flipped copy of the current mask.
|
|
base::UniquePtr<Mask> newMask(new Mask(*mask));
|
|
newMask->freeze();
|
|
raster::algorithm::flip_image(newMask->getBitmap(),
|
|
gfx::Rect(gfx::Point(0, 0),
|
|
gfx::Size(maskBitmap->w, maskBitmap->h)),
|
|
m_flipType);
|
|
newMask->unfreeze();
|
|
|
|
// Change the current mask and generate the new boundaries.
|
|
api.copyToCurrentMask(newMask);
|
|
|
|
document->generateMaskBoundaries();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Flip the portion of image specified by "bounds" variable.
|
|
if (!alreadyFlipped) {
|
|
api.flipImage(image, bounds, m_flipType);
|
|
}
|
|
}
|
|
else {
|
|
// get all sprite cels
|
|
CelList cels;
|
|
sprite->getCels(cels);
|
|
|
|
// for each cel...
|
|
for (CelIterator it = cels.begin(); it != cels.end(); ++it) {
|
|
Cel* cel = *it;
|
|
Image* image = sprite->getStock()->getImage(cel->getImage());
|
|
|
|
api.setCelPosition
|
|
(sprite, cel,
|
|
(m_flipType == raster::algorithm::FlipHorizontal ?
|
|
sprite->getWidth() - image->w - cel->getX():
|
|
cel->getX()),
|
|
(m_flipType == raster::algorithm::FlipVertical ?
|
|
sprite->getHeight() - image->h - cel->getY():
|
|
cel->getY()));
|
|
|
|
api.flipImage(image, gfx::Rect(0, 0, image->w, image->h), m_flipType);
|
|
}
|
|
}
|
|
|
|
undoTransaction.commit();
|
|
}
|
|
|
|
update_screen_for_document(document);
|
|
}
|
|
|
|
Command* CommandFactory::createFlipCommand()
|
|
{
|
|
return new FlipCommand;
|
|
}
|
|
|
|
} // namespace app
|