1// Aseprite
2// Copyright (C) 2020-2022 Igara Studio S.A.
3// Copyright (C) 2016-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_layer_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/layer.h"
23#include "fmt/format.h"
24
25#include <string>
26
27namespace app {
28
29class LayerOpacityCommand : public Command {
30public:
31 LayerOpacityCommand();
32
33protected:
34 bool onNeedsParams() const override { return true; }
35 void onLoadParams(const Params& params) override;
36 bool onEnabled(Context* context) override;
37 void onExecute(Context* context) override;
38 std::string onGetFriendlyName() const override;
39
40private:
41 int m_opacity;
42};
43
44LayerOpacityCommand::LayerOpacityCommand()
45 : Command(CommandId::LayerOpacity(), CmdUIOnlyFlag)
46{
47 m_opacity = 255;
48}
49
50void LayerOpacityCommand::onLoadParams(const Params& params)
51{
52 m_opacity = params.get_as<int>("opacity");
53 m_opacity = std::clamp(m_opacity, 0, 255);
54}
55
56bool LayerOpacityCommand::onEnabled(Context* context)
57{
58 return context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
59 ContextFlags::HasActiveLayer);
60}
61
62void LayerOpacityCommand::onExecute(Context* context)
63{
64 ContextWriter writer(context);
65 Layer* layer = writer.layer();
66 if (!layer ||
67 !layer->isImage() ||
68 static_cast<LayerImage*>(layer)->opacity() == m_opacity)
69 return;
70
71 {
72 Tx tx(writer.context(), "Set Layer Opacity");
73
74 // TODO the range of selected frames should be in app::Site.
75 SelectedLayers selLayers;
76 auto range = App::instance()->timeline()->range();
77 if (range.enabled()) {
78 selLayers = range.selectedLayers();
79 }
80 else {
81 selLayers.insert(writer.layer());
82 }
83
84 for (auto layer : selLayers) {
85 if (layer->isImage())
86 tx(new cmd::SetLayerOpacity(static_cast<LayerImage*>(layer), m_opacity));
87 }
88
89 tx.commit();
90 }
91
92 update_screen_for_document(writer.document());
93}
94
95std::string LayerOpacityCommand::onGetFriendlyName() const
96{
97 return fmt::format(getBaseFriendlyName(),
98 m_opacity,
99 int(100.0 * m_opacity / 255.0));
100}
101
102Command* CommandFactory::createLayerOpacityCommand()
103{
104 return new LayerOpacityCommand;
105}
106
107} // namespace app
108