aseprite/src/app/commands/cmd_modify_selection.cpp

176 lines
4.9 KiB
C++

// Aseprite
// Copyright (C) 2019-2024 Igara Studio S.A.
// Copyright (C) 2015-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/cmd/set_mask.h"
#include "app/commands/command.h"
#include "app/commands/params.h"
#include "app/context_access.h"
#include "app/doc.h"
#include "app/i18n/strings.h"
#include "app/modules/gui.h"
#include "app/pref/preferences.h"
#include "app/tx.h"
#include "doc/algorithm/modify_selection.h"
#include "doc/brush_type.h"
#include "doc/mask.h"
#include "modify_selection.xml.h"
namespace app {
using namespace doc;
typedef doc::algorithm::SelectionModifier Modifier;
class ModifySelectionWindow : public app::gen::ModifySelection {};
class ModifySelectionCommand : public Command {
public:
ModifySelectionCommand();
protected:
void onLoadParams(const Params& params) override;
bool onEnabled(Context* context) override;
void onExecute(Context* context) override;
std::string onGetFriendlyName() const override;
bool isListed(const Params& params) const override { return !params.empty(); }
private:
std::string getActionName() const;
Modifier m_modifier;
int m_quantity;
doc::BrushType m_brushType;
bool m_ui;
};
ModifySelectionCommand::ModifySelectionCommand()
: Command(CommandId::ModifySelection())
, m_modifier(Modifier::Expand)
, m_quantity(0)
, m_brushType(doc::kCircleBrushType)
, m_ui(true)
{
}
void ModifySelectionCommand::onLoadParams(const Params& params)
{
const std::string modifier = params.get("modifier");
if (modifier == "border")
m_modifier = Modifier::Border;
else if (modifier == "expand")
m_modifier = Modifier::Expand;
else if (modifier == "contract")
m_modifier = Modifier::Contract;
const int quantity = params.get_as<int>("quantity");
m_quantity = std::max<int>(0, quantity);
const std::string brush = params.get("brush");
if (brush == "circle")
m_brushType = doc::kCircleBrushType;
else if (brush == "square")
m_brushType = doc::kSquareBrushType;
if (params.has_param("ui"))
m_ui = params.get_as<bool>("ui");
else
m_ui = true;
}
bool ModifySelectionCommand::onEnabled(Context* context)
{
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable | ContextFlags::HasVisibleMask);
}
void ModifySelectionCommand::onExecute(Context* context)
{
int quantity = m_quantity;
doc::BrushType brush = m_brushType;
if (quantity == 0 && m_ui && context->isUIAvailable()) {
Preferences& pref = Preferences::instance();
ModifySelectionWindow window;
window.setText(getActionName() + " Selection");
if (m_modifier == Modifier::Border)
window.byLabel()->setText("Width:");
else
window.byLabel()->setText(getActionName() + " By:");
window.quantity()->setTextf("%d", pref.selection.modifySelectionQuantity());
brush = (pref.selection.modifySelectionBrush() == app::gen::BrushType::CIRCLE ?
doc::kCircleBrushType :
doc::kSquareBrushType);
window.circle()->setSelected(brush == doc::kCircleBrushType);
window.square()->setSelected(brush == doc::kSquareBrushType);
window.openWindowInForeground();
if (window.closer() != window.ok())
return;
quantity = window.quantity()->textInt();
quantity = std::clamp(quantity, 1, 100);
brush = (window.circle()->isSelected() ? doc::kCircleBrushType : doc::kSquareBrushType);
pref.selection.modifySelectionQuantity(quantity);
pref.selection.modifySelectionBrush(
(brush == doc::kCircleBrushType ? app::gen::BrushType::CIRCLE : app::gen::BrushType::SQUARE));
}
// Lock sprite
ContextWriter writer(context);
Doc* document(writer.document());
Sprite* sprite(writer.sprite());
std::unique_ptr<Mask> mask(new Mask);
{
mask->reserve(sprite->bounds());
mask->freeze();
doc::algorithm::modify_selection(m_modifier, document->mask(), mask.get(), quantity, brush);
mask->unfreeze();
}
// Set the new mask
Tx tx(writer, friendlyName(), DoesntModifyDocument);
tx(new cmd::SetMask(document, mask.get()));
tx.commit();
update_screen_for_document(document);
}
std::string ModifySelectionCommand::onGetFriendlyName() const
{
std::string quantity;
if (m_quantity > 0)
quantity = Strings::commands_ModifySelection_Quantity(m_quantity);
return Strings::commands_ModifySelection(getActionName(), quantity);
}
std::string ModifySelectionCommand::getActionName() const
{
switch (m_modifier) {
case Modifier::Border: return Strings::commands_ModifySelection_Border();
case Modifier::Expand: return Strings::commands_ModifySelection_Expand();
case Modifier::Contract: return Strings::commands_ModifySelection_Contract();
default: return Strings::commands_ModifySelection_Modify();
}
}
Command* CommandFactory::createModifySelectionCommand()
{
return new ModifySelectionCommand;
}
} // namespace app