1 /*
2 * Copyright (C) 2020 Rerrah
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
11 * conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26 #include "change_values_in_pattern_command.hpp"
27 #include "misc.hpp"
28
ChangeValuesInPatternCommand(std::weak_ptr<Module> mod,int songNum,int beginTrack,int beginColumn,int beginOrder,int beginStep,int endTrack,int endColumn,int endStep,int value,bool isFMReversed)29 ChangeValuesInPatternCommand::ChangeValuesInPatternCommand(std::weak_ptr<Module> mod, int songNum, int beginTrack,
30 int beginColumn, int beginOrder, int beginStep,
31 int endTrack, int endColumn, int endStep, int value, bool isFMReversed)
32 : mod_(mod),
33 song_(songNum),
34 bTrack_(beginTrack),
35 bCol_(beginColumn),
36 order_(beginOrder),
37 bStep_(beginStep),
38 eTrack_(endTrack),
39 eCol_(endColumn),
40 eStep_(endStep),
41 diff_(value),
42 fmReverse_(isFMReversed)
43 {
44 auto& sng = mod.lock()->getSong(songNum);
45
46 for (int step = beginStep; step <= endStep; ++step) {
47 int track = beginTrack;
48 int col = beginColumn;
49 std::vector<int> vals;
50 while (true) {
51 int val;
52 Step& st = sng.getTrack(track).getPatternFromOrderNumber(beginOrder).getStep(step);
53 switch (col) {
54 case 1: val = st.getInstrumentNumber(); break;
55 case 2: val = st.getVolume(); break;
56 case 4: val = st.getEffectValue(0); break;
57 case 6: val = st.getEffectValue(1); break;
58 case 8: val = st.getEffectValue(2); break;
59 case 10: val = st.getEffectValue(3); break;
60 default: val = -1; break;
61 }
62 if (val > -1) vals.push_back(val);
63 if (track == endTrack && col == endColumn) break;
64 track += (++col / 11);
65 col %= 11;
66 }
67 prevVals_.push_back(vals);
68 }
69 }
70
redo()71 void ChangeValuesInPatternCommand::redo()
72 {
73 auto& sng = mod_.lock()->getSong(song_);
74 auto it = prevVals_.begin();
75 for (int step = bStep_; step <= eStep_; ++step, ++it) {
76 int track = bTrack_;
77 int col = bCol_;
78 auto valit = it->begin();
79 while (true) {
80 Track& tr = sng.getTrack(track);
81 Step& st = tr.getPatternFromOrderNumber(order_).getStep(step);
82 switch (col) {
83 case 1:
84 if (st.getInstrumentNumber() > -1) st.setInstrumentNumber(clamp(diff_ + *valit++, 0, 127));
85 break;
86 case 2:
87 if (st.getVolume() > -1) {
88 int d = (tr.getAttribute().source == SoundSource::FM && fmReverse_) ? -diff_ : diff_;
89 st.setVolume(clamp(d + *valit++, 0, 255));
90 }
91 break;
92 case 4:
93 if (st.getEffectValue(0) > -1) st.setEffectValue(0, clamp(diff_ + *valit++, 0, 255));
94 break;
95 case 6:
96 if (st.getEffectValue(1) > -1) st.setEffectValue(1, clamp(diff_ + *valit++, 0, 255));
97 break;
98 case 8:
99 if (st.getEffectValue(2) > -1) st.setEffectValue(2, clamp(diff_ + *valit++, 0, 255));
100 break;
101 case 10:
102 if (st.getEffectValue(3) > -1) st.setEffectValue(3, clamp(diff_ + *valit++, 0, 255));
103 break;
104 default:
105 break;
106 }
107 if (track == eTrack_ && col == eCol_) break;
108 track += (++col / 11);
109 col %= 11;
110 }
111 }
112 }
113
undo()114 void ChangeValuesInPatternCommand::undo()
115 {
116 auto& sng = mod_.lock()->getSong(song_);
117 auto it = prevVals_.begin();
118 for (int step = bStep_; step <= eStep_; ++step, ++it) {
119 int track = bTrack_;
120 int col = bCol_;
121 auto valit = it->begin();
122 while (true) {
123 Step& st = sng.getTrack(track).getPatternFromOrderNumber(order_).getStep(step);
124 switch (col) {
125 case 1:
126 if (st.getInstrumentNumber() > -1) st.setInstrumentNumber(*valit++);
127 break;
128 case 2:
129 if (st.getVolume() > -1) st.setVolume(*valit++);
130 break;
131 case 4:
132 if (st.getEffectValue(0) > -1) st.setEffectValue(0, *valit++);
133 break;
134 case 6:
135 if (st.getEffectValue(1) > -1) st.setEffectValue(1, *valit++);
136 break;
137 case 8:
138 if (st.getEffectValue(2) > -1) st.setEffectValue(2, *valit++);
139 break;
140 case 10:
141 if (st.getEffectValue(3) > -1) st.setEffectValue(3, *valit++);
142 break;
143 default:
144 break;
145 }
146 if (track == eTrack_ && col == eCol_) break;
147 track += (++col / 11);
148 col %= 11;
149 }
150 }
151 }
152
getID() const153 CommandId ChangeValuesInPatternCommand::getID() const
154 {
155 return CommandId::ChangeValuesInPattern;
156 }
157