2018-05-31 03:53:20 +08:00
|
|
|
// Aseprite
|
2022-10-20 23:31:22 +08:00
|
|
|
// Copyright (C) 2019-2022 Igara Studio S.A.
|
2018-05-31 03:53:20 +08:00
|
|
|
// Copyright (C) 2018 David Capello
|
|
|
|
//
|
|
|
|
// 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/cmd/clear_mask.h"
|
|
|
|
#include "app/cmd/trim_cel.h"
|
|
|
|
#include "app/color_utils.h"
|
|
|
|
#include "app/commands/command.h"
|
|
|
|
#include "app/context_access.h"
|
|
|
|
#include "app/pref/preferences.h"
|
2018-08-21 03:00:59 +08:00
|
|
|
#include "app/tx.h"
|
2018-05-31 03:53:20 +08:00
|
|
|
#include "app/ui/editor/editor.h"
|
|
|
|
#include "app/util/expand_cel_canvas.h"
|
2018-05-31 05:05:18 +08:00
|
|
|
#include "doc/algorithm/fill_selection.h"
|
|
|
|
#include "doc/algorithm/stroke_selection.h"
|
2018-05-31 03:53:20 +08:00
|
|
|
#include "doc/mask.h"
|
|
|
|
|
|
|
|
namespace app {
|
|
|
|
|
|
|
|
class FillCommand : public Command {
|
|
|
|
public:
|
2018-05-31 05:05:18 +08:00
|
|
|
enum Type { Fill, Stroke };
|
|
|
|
FillCommand(Type type);
|
2018-05-31 03:53:20 +08:00
|
|
|
protected:
|
|
|
|
bool onEnabled(Context* ctx) override;
|
|
|
|
void onExecute(Context* ctx) override;
|
2018-05-31 05:05:18 +08:00
|
|
|
private:
|
|
|
|
Type m_type;
|
2018-05-31 03:53:20 +08:00
|
|
|
};
|
|
|
|
|
2018-05-31 05:05:18 +08:00
|
|
|
FillCommand::FillCommand(Type type)
|
|
|
|
: Command(type == Stroke ? CommandId::Stroke():
|
|
|
|
CommandId::Fill(), CmdUIOnlyFlag)
|
|
|
|
, m_type(type)
|
2018-05-31 03:53:20 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FillCommand::onEnabled(Context* ctx)
|
|
|
|
{
|
|
|
|
if (ctx->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
|
|
|
ContextFlags::ActiveLayerIsVisible |
|
|
|
|
ContextFlags::ActiveLayerIsEditable |
|
|
|
|
ContextFlags::ActiveLayerIsImage)) {
|
|
|
|
return true;
|
|
|
|
}
|
2024-09-03 10:12:13 +08:00
|
|
|
auto* editor = Editor::activeEditor();
|
2022-10-20 23:31:22 +08:00
|
|
|
if (editor && editor->isMovingPixels()) {
|
2018-05-31 03:53:20 +08:00
|
|
|
return true;
|
|
|
|
}
|
2022-10-20 23:31:22 +08:00
|
|
|
return false;
|
2018-05-31 03:53:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void FillCommand::onExecute(Context* ctx)
|
|
|
|
{
|
|
|
|
ContextWriter writer(ctx);
|
|
|
|
Site site = *writer.site();
|
2018-07-07 22:54:44 +08:00
|
|
|
Doc* doc = site.document();
|
2018-05-31 03:53:20 +08:00
|
|
|
Sprite* sprite = site.sprite();
|
2018-05-31 05:05:18 +08:00
|
|
|
Layer* layer = site.layer();
|
2018-05-31 03:53:20 +08:00
|
|
|
Mask* mask = doc->mask();
|
2018-05-31 05:05:18 +08:00
|
|
|
if (!doc || !sprite ||
|
|
|
|
!layer || !layer->isImage() ||
|
|
|
|
!mask || !doc->isMaskVisible())
|
2018-05-31 03:53:20 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
Preferences& pref = Preferences::instance();
|
2020-08-28 07:32:22 +08:00
|
|
|
doc::color_t color;
|
|
|
|
if (site.tilemapMode() == TilemapMode::Tiles)
|
|
|
|
color = pref.colorBar.fgTile();
|
|
|
|
else
|
|
|
|
color = color_utils::color_for_layer(pref.colorBar.fgColor(), layer);
|
2018-05-31 03:53:20 +08:00
|
|
|
|
|
|
|
{
|
2023-12-13 08:34:30 +08:00
|
|
|
Tx tx(writer, "Fill Selection with Foreground Color");
|
2018-05-31 03:53:20 +08:00
|
|
|
{
|
|
|
|
ExpandCelCanvas expand(
|
2018-05-31 05:05:18 +08:00
|
|
|
site, layer,
|
2018-08-21 03:00:59 +08:00
|
|
|
TiledMode::NONE, tx,
|
2018-05-31 03:53:20 +08:00
|
|
|
ExpandCelCanvas::None);
|
|
|
|
|
|
|
|
gfx::Region rgn(sprite->bounds() |
|
|
|
|
mask->bounds());
|
|
|
|
expand.validateDestCanvas(rgn);
|
|
|
|
|
2020-08-28 07:32:22 +08:00
|
|
|
gfx::Rect imageBounds(expand.getCel()->position(),
|
|
|
|
expand.getDestCanvas()->size());
|
|
|
|
doc::Grid grid = site.grid();
|
|
|
|
|
|
|
|
if (site.tilemapMode() == TilemapMode::Tiles)
|
|
|
|
imageBounds = grid.tileToCanvas(imageBounds);
|
2018-05-31 05:05:18 +08:00
|
|
|
|
|
|
|
if (m_type == Stroke) {
|
|
|
|
doc::algorithm::stroke_selection(
|
|
|
|
expand.getDestCanvas(),
|
2020-08-28 07:32:22 +08:00
|
|
|
imageBounds,
|
2018-05-31 05:05:18 +08:00
|
|
|
mask,
|
2020-08-28 07:32:22 +08:00
|
|
|
color,
|
|
|
|
(site.tilemapMode() == TilemapMode::Tiles ? &grid: nullptr));
|
2018-05-31 05:05:18 +08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
doc::algorithm::fill_selection(
|
|
|
|
expand.getDestCanvas(),
|
2020-08-28 07:32:22 +08:00
|
|
|
imageBounds,
|
2018-05-31 05:05:18 +08:00
|
|
|
mask,
|
2020-08-28 07:32:22 +08:00
|
|
|
color,
|
|
|
|
(site.tilemapMode() == TilemapMode::Tiles ? &grid: nullptr));
|
2018-05-31 05:05:18 +08:00
|
|
|
}
|
2018-05-31 03:53:20 +08:00
|
|
|
|
|
|
|
expand.commit();
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the cel wasn't deleted by cmd::ClearMask, we trim it.
|
2018-05-31 05:05:18 +08:00
|
|
|
Cel* cel = ctx->activeSite().cel();
|
2021-02-23 03:39:40 +08:00
|
|
|
if (site.shouldTrimCel(cel))
|
2018-08-21 03:00:59 +08:00
|
|
|
tx(new cmd::TrimCel(cel));
|
2018-05-31 03:53:20 +08:00
|
|
|
|
2018-08-21 03:00:59 +08:00
|
|
|
tx.commit();
|
2018-05-31 03:53:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
doc->notifyGeneralUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
Command* CommandFactory::createFillCommand()
|
|
|
|
{
|
2018-05-31 05:05:18 +08:00
|
|
|
return new FillCommand(FillCommand::Fill);
|
|
|
|
}
|
|
|
|
|
|
|
|
Command* CommandFactory::createStrokeCommand()
|
|
|
|
{
|
|
|
|
return new FillCommand(FillCommand::Stroke);
|
2018-05-31 03:53:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace app
|