1 // Aseprite
2 // Copyright (C) 2015-2017  David Capello
3 //
4 // This program is distributed under the terms of
5 // the End-User License Agreement for Aseprite.
6 
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10 
11 #include "app/cmd/set_mask.h"
12 #include "app/commands/command.h"
13 #include "app/context_access.h"
14 #include "app/doc.h"
15 #include "app/i18n/strings.h"
16 #include "app/modules/editors.h"
17 #include "app/modules/gui.h"
18 #include "app/pref/preferences.h"
19 #include "app/snap_to_grid.h"
20 #include "app/transaction.h"
21 #include "app/ui/editor/editor.h"
22 #include "doc/mask.h"
23 #include "fmt/format.h"
24 #include "ui/system.h"
25 
26 namespace app {
27 
28 using namespace doc;
29 
30 class SelectTileCommand : public Command {
31 public:
32   SelectTileCommand();
clone() const33   Command* clone() const override { return new SelectTileCommand(*this); }
34 
35 protected:
36   void onLoadParams(const Params& params) override;
37   bool onEnabled(Context* ctx) override;
38   void onExecute(Context* ctx) override;
39   std::string onGetFriendlyName() const override;
40 
41 private:
42   gen::SelectionMode m_mode;
43 };
44 
SelectTileCommand()45 SelectTileCommand::SelectTileCommand()
46   : Command(CommandId::SelectTile(), CmdRecordableFlag)
47   , m_mode(gen::SelectionMode::DEFAULT)
48 {
49 }
50 
onLoadParams(const Params & params)51 void SelectTileCommand::onLoadParams(const Params& params)
52 {
53   std::string mode = params.get("mode");
54   if (mode == "add")
55     m_mode = gen::SelectionMode::ADD;
56   else if (mode == "subtract")
57     m_mode = gen::SelectionMode::SUBTRACT;
58   else
59     m_mode = gen::SelectionMode::DEFAULT;
60 }
61 
onEnabled(Context * ctx)62 bool SelectTileCommand::onEnabled(Context* ctx)
63 {
64   return ctx->checkFlags(ContextFlags::ActiveDocumentIsWritable);
65 }
66 
onExecute(Context * ctx)67 void SelectTileCommand::onExecute(Context* ctx)
68 {
69   if (!current_editor ||
70       !current_editor->hasMouse())
71     return;
72 
73   // Lock sprite
74   ContextWriter writer(ctx);
75   Doc* doc(writer.document());
76   auto& docPref = Preferences::instance().document(doc);
77 
78   base::UniquePtr<Mask> mask(new Mask());
79 
80   if (m_mode != gen::SelectionMode::DEFAULT)
81     mask->copyFrom(doc->mask());
82 
83   {
84     gfx::Rect gridBounds = docPref.grid.bounds();
85     gfx::Point pos = current_editor->screenToEditor(ui::get_mouse_position());
86     pos = snap_to_grid(gridBounds, pos, PreferSnapTo::BoxOrigin);
87     gridBounds.setOrigin(pos);
88 
89     if (m_mode != gen::SelectionMode::SUBTRACT)
90       mask->add(gridBounds);
91     else
92       mask->subtract(gridBounds);
93   }
94 
95   // Set the new mask
96   Transaction transaction(writer.context(),
97                           friendlyName(),
98                           DoesntModifyDocument);
99   transaction.execute(new cmd::SetMask(doc, mask));
100   transaction.commit();
101 
102   doc->generateMaskBoundaries();
103   update_screen_for_document(doc);
104 }
105 
onGetFriendlyName() const106 std::string SelectTileCommand::onGetFriendlyName() const
107 {
108   std::string text;
109   switch (m_mode) {
110     case gen::SelectionMode::ADD:
111       text = Strings::commands_SelectTile_Add();
112       break;
113     case gen::SelectionMode::SUBTRACT:
114       text = Strings::commands_SelectTile_Subtract();
115       break;
116     default:
117       text = getBaseFriendlyName();;
118       break;
119   }
120   return text;
121 }
122 
createSelectTileCommand()123 Command* CommandFactory::createSelectTileCommand()
124 {
125   return new SelectTileCommand;
126 }
127 
128 } // namespace app
129