1// Aseprite
2// Copyright (C) 2020-2022 Igara Studio S.A.
3// Copyright (C) 2018 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "app/app.h"
13#include "app/cmd/set_cel_opacity.h"
14#include "app/commands/command.h"
15#include "app/commands/params.h"
16#include "app/context.h"
17#include "app/context_access.h"
18#include "app/i18n/strings.h"
19#include "app/modules/gui.h"
20#include "app/tx.h"
21#include "app/ui/timeline/timeline.h"
22#include "doc/cel.h"
23#include "doc/cels_range.h"
24#include "doc/sprite.h"
25#include "fmt/format.h"
26
27#include <string>
28
29namespace app {
30
31class CelOpacityCommand : public Command {
32public:
33 CelOpacityCommand();
34
35protected:
36 bool onNeedsParams() const override { return true; }
37 void onLoadParams(const Params& params) override;
38 bool onEnabled(Context* context) override;
39 void onExecute(Context* context) override;
40 std::string onGetFriendlyName() const override;
41
42private:
43 int m_opacity;
44};
45
46CelOpacityCommand::CelOpacityCommand()
47 : Command(CommandId::CelOpacity(), CmdUIOnlyFlag)
48{
49 m_opacity = 255;
50}
51
52void CelOpacityCommand::onLoadParams(const Params& params)
53{
54 m_opacity = params.get_as<int>("opacity");
55 m_opacity = std::clamp(m_opacity, 0, 255);
56}
57
58bool CelOpacityCommand::onEnabled(Context* context)
59{
60 return context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
61 ContextFlags::HasActiveCel);
62}
63
64void CelOpacityCommand::onExecute(Context* context)
65{
66 ContextWriter writer(context);
67 Layer* layer = writer.layer();
68 Cel* cel = writer.cel();
69 if (!cel ||
70 layer->isBackground() ||
71 !layer->isEditable() ||
72 cel->opacity() == m_opacity)
73 return;
74
75 {
76 Tx tx(writer.context(), "Set Cel Opacity");
77
78 // TODO the range of selected cels should be in app::Site.
79 DocRange range;
80
81#ifdef ENABLE_UI
82 if (context->isUIAvailable())
83 range = App::instance()->timeline()->range();
84#endif
85
86 if (!range.enabled()) {
87 range.startRange(layer, cel->frame(), DocRange::kCels);
88 range.endRange(layer, cel->frame());
89 }
90
91 for (Cel* c : cel->sprite()->uniqueCels(range.selectedFrames())) {
92 if (range.contains(c->layer())) {
93 if (!c->layer()->isBackground() &&
94 c->layer()->isEditable() &&
95 m_opacity != c->opacity()) {
96 tx(new cmd::SetCelOpacity(c, m_opacity));
97 }
98 }
99 }
100
101 tx.commit();
102 }
103
104#ifdef ENABLE_UI
105 if (context->isUIAvailable())
106 update_screen_for_document(writer.document());
107#endif
108}
109
110std::string CelOpacityCommand::onGetFriendlyName() const
111{
112 return fmt::format(getBaseFriendlyName(),
113 m_opacity,
114 int(100.0 * m_opacity / 255.0));
115}
116
117Command* CommandFactory::createCelOpacityCommand()
118{
119 return new CelOpacityCommand;
120}
121
122} // namespace app
123