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/commands/command.h" |
13 | #include "app/commands/params.h" |
14 | #include "app/context.h" |
15 | #include "app/context_access.h" |
16 | #include "app/doc_api.h" |
17 | #include "app/pref/preferences.h" |
18 | #include "app/tx.h" |
19 | #include "base/convert_to.h" |
20 | #include "doc/sprite.h" |
21 | #include "ui/ui.h" |
22 | |
23 | #include "frame_properties.xml.h" |
24 | |
25 | namespace app { |
26 | |
27 | using namespace ui; |
28 | |
29 | class FramePropertiesCommand : public Command { |
30 | public: |
31 | FramePropertiesCommand(); |
32 | |
33 | protected: |
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 | |
39 | private: |
40 | enum Target { |
41 | ALL_FRAMES = -1, |
42 | CURRENT_RANGE = 0, |
43 | SPECIFIC_FRAME = 1 |
44 | }; |
45 | |
46 | // Frame to be shown. It can be ALL_FRAMES, CURRENT_RANGE, or a |
47 | // number indicating a specific frame (1 is the first frame). |
48 | Target m_target; |
49 | frame_t m_frame; |
50 | }; |
51 | |
52 | FramePropertiesCommand::FramePropertiesCommand() |
53 | : Command(CommandId::FrameProperties(), CmdUIOnlyFlag) |
54 | { |
55 | } |
56 | |
57 | void FramePropertiesCommand::onLoadParams(const Params& params) |
58 | { |
59 | std::string frame = params.get("frame" ); |
60 | if (frame == "all" ) { |
61 | m_target = ALL_FRAMES; |
62 | } |
63 | else if (frame == "current" ) { |
64 | m_target = CURRENT_RANGE; |
65 | } |
66 | else { |
67 | m_target = SPECIFIC_FRAME; |
68 | m_frame = frame_t(base::convert_to<int>(frame)); |
69 | } |
70 | } |
71 | |
72 | bool FramePropertiesCommand::onEnabled(Context* context) |
73 | { |
74 | return context->checkFlags(ContextFlags::ActiveDocumentIsWritable); |
75 | } |
76 | |
77 | void FramePropertiesCommand::onExecute(Context* context) |
78 | { |
79 | const ContextReader reader(context); |
80 | const Sprite* sprite = reader.sprite(); |
81 | auto& docPref = Preferences::instance().document(context->activeDocument()); |
82 | int base = docPref.timeline.firstFrame(); |
83 | app::gen::FrameProperties window; |
84 | SelectedFrames selFrames; |
85 | |
86 | switch (m_target) { |
87 | |
88 | case ALL_FRAMES: |
89 | selFrames.insert(0, sprite->lastFrame()); |
90 | break; |
91 | |
92 | case CURRENT_RANGE: { |
93 | Site site = context->activeSite(); |
94 | if (site.inTimeline()) { |
95 | selFrames = site.selectedFrames(); |
96 | } |
97 | else { |
98 | selFrames.insert(site.frame()); |
99 | } |
100 | break; |
101 | } |
102 | |
103 | case SPECIFIC_FRAME: |
104 | selFrames.insert(m_frame-base); |
105 | break; |
106 | } |
107 | |
108 | ASSERT(!selFrames.empty()); |
109 | if (selFrames.empty()) |
110 | return; |
111 | |
112 | if (selFrames.size() == 1) |
113 | window.frame()->setTextf("%d" , selFrames.firstFrame()+base); |
114 | else if (selFrames.ranges() == 1) { |
115 | window.frame()->setTextf("[%d...%d]" , |
116 | selFrames.firstFrame()+base, |
117 | selFrames.lastFrame()+base); |
118 | } |
119 | else |
120 | window.frame()->setTextf("Multiple Frames" ); |
121 | |
122 | window.frlen()->setTextf( |
123 | "%d" , sprite->frameDuration(selFrames.firstFrame())); |
124 | |
125 | window.openWindowInForeground(); |
126 | if (window.closer() == window.ok()) { |
127 | int newMsecs = window.frlen()->textInt(); |
128 | |
129 | ContextWriter writer(reader); |
130 | Tx tx(writer.context(), "Frame Duration" ); |
131 | DocApi api = writer.document()->getApi(tx); |
132 | |
133 | for (frame_t frame : selFrames) |
134 | api.setFrameDuration(writer.sprite(), frame, newMsecs); |
135 | |
136 | tx.commit(); |
137 | } |
138 | } |
139 | |
140 | Command* CommandFactory::createFramePropertiesCommand() |
141 | { |
142 | return new FramePropertiesCommand; |
143 | } |
144 | |
145 | } // namespace app |
146 | |