1 | // Aseprite |
2 | // Copyright (C) 2001-2018 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/app.h" |
12 | #include "app/cmd/add_tag.h" |
13 | #include "app/cmd/remove_tag.h" |
14 | #include "app/cmd/set_tag_range.h" |
15 | #include "app/commands/command.h" |
16 | #include "app/commands/commands.h" |
17 | #include "app/commands/params.h" |
18 | #include "app/context_access.h" |
19 | #include "app/loop_tag.h" |
20 | #include "app/tx.h" |
21 | #include "app/ui/timeline/timeline.h" |
22 | #include "doc/tag.h" |
23 | |
24 | namespace app { |
25 | |
26 | class SetLoopSectionCommand : public Command { |
27 | public: |
28 | enum class Action { Auto, On, Off }; |
29 | |
30 | SetLoopSectionCommand(); |
31 | |
32 | protected: |
33 | void onLoadParams(const Params& params) override; |
34 | bool onEnabled(Context* context) override; |
35 | void onExecute(Context* context) override; |
36 | |
37 | Action m_action; |
38 | doc::frame_t m_begin, m_end; |
39 | }; |
40 | |
41 | SetLoopSectionCommand::SetLoopSectionCommand() |
42 | : Command(CommandId::SetLoopSection(), CmdRecordableFlag) |
43 | , m_action(Action::Auto) |
44 | , m_begin(0) |
45 | , m_end(0) |
46 | { |
47 | } |
48 | |
49 | void SetLoopSectionCommand::onLoadParams(const Params& params) |
50 | { |
51 | std::string action = params.get("action" ); |
52 | if (action == "on" ) m_action = Action::On; |
53 | else if (action == "off" ) m_action = Action::Off; |
54 | else m_action = Action::Auto; |
55 | |
56 | std::string begin = params.get("begin" ); |
57 | std::string end = params.get("end" ); |
58 | |
59 | m_begin = frame_t(strtol(begin.c_str(), NULL, 10)); |
60 | m_end = frame_t(strtol(end.c_str(), NULL, 10)); |
61 | } |
62 | |
63 | bool SetLoopSectionCommand::onEnabled(Context* ctx) |
64 | { |
65 | return ctx->checkFlags(ContextFlags::HasActiveDocument); |
66 | } |
67 | |
68 | void SetLoopSectionCommand::onExecute(Context* ctx) |
69 | { |
70 | Doc* doc = ctx->activeDocument(); |
71 | if (!doc) |
72 | return; |
73 | |
74 | doc::Sprite* sprite = doc->sprite(); |
75 | doc::frame_t begin = m_begin; |
76 | doc::frame_t end = m_end; |
77 | bool on = false; |
78 | |
79 | switch (m_action) { |
80 | |
81 | case Action::Auto: { |
82 | auto range = App::instance()->timeline()->range(); |
83 | if (range.enabled() && (range.frames() > 1)) { |
84 | begin = range.selectedFrames().firstFrame(); |
85 | end = range.selectedFrames().lastFrame(); |
86 | on = true; |
87 | } |
88 | else { |
89 | on = false; |
90 | } |
91 | break; |
92 | } |
93 | |
94 | case Action::On: |
95 | on = true; |
96 | break; |
97 | |
98 | case Action::Off: |
99 | on = false; |
100 | break; |
101 | |
102 | } |
103 | |
104 | doc::Tag* loopTag = get_loop_tag(sprite); |
105 | if (on) { |
106 | if (!loopTag) { |
107 | loopTag = create_loop_tag(begin, end); |
108 | |
109 | ContextWriter writer(ctx); |
110 | Tx tx(writer.context(), "Add Loop" ); |
111 | tx(new cmd::AddTag(sprite, loopTag)); |
112 | tx.commit(); |
113 | } |
114 | else if (loopTag->fromFrame() != begin || |
115 | loopTag->toFrame() != end) { |
116 | ContextWriter writer(ctx); |
117 | Tx tx(writer.context(), "Set Loop Range" ); |
118 | tx(new cmd::SetTagRange(loopTag, begin, end)); |
119 | tx.commit(); |
120 | } |
121 | else { |
122 | Command* cmd = Commands::instance()->byId(CommandId::FrameTagProperties()); |
123 | ctx->executeCommand(cmd); |
124 | } |
125 | } |
126 | else { |
127 | if (loopTag) { |
128 | ContextWriter writer(ctx); |
129 | Tx tx(writer.context(), "Remove Loop" ); |
130 | tx(new cmd::RemoveTag(sprite, loopTag)); |
131 | tx.commit(); |
132 | } |
133 | } |
134 | |
135 | App::instance()->timeline()->invalidate(); |
136 | } |
137 | |
138 | Command* CommandFactory::createSetLoopSectionCommand() |
139 | { |
140 | return new SetLoopSectionCommand; |
141 | } |
142 | |
143 | } // namespace app |
144 | |