1
2
3 #include "toonz/doubleparamcmd.h"
4 #include "toonz/preferences.h"
5 #include "toonz/tscenehandle.h"
6 #include "tdoubleparam.h"
7 #include "tdoublekeyframe.h"
8 #include "tundo.h"
9 #include "tunit.h"
10 #include <QString>
11 #include <map>
12
13 //=============================================================================
14 //
15 // Keyframes Undo
16 //
17 //-----------------------------------------------------------------------------
18
19 class KeyframesUndo final : public TUndo {
20 TDoubleParamP m_param;
21 typedef std::map<int, TDoubleKeyframe> Keyframes;
22 Keyframes m_oldKeyframes;
23 Keyframes m_newKeyframes;
24
25 public:
KeyframesUndo(TDoubleParam * param)26 KeyframesUndo(TDoubleParam *param) : m_param(param) {}
addKeyframe(int kIndex)27 void addKeyframe(int kIndex) {
28 if (m_oldKeyframes.count(kIndex) > 0) return;
29 assert(0 <= kIndex && kIndex < m_param->getKeyframeCount());
30 m_oldKeyframes[kIndex] = m_param->getKeyframe(kIndex);
31 }
createKeyframe(double frame)32 int createKeyframe(double frame) {
33 TDoubleKeyframe oldKeyframe = m_param->getKeyframeAt(frame);
34 if (oldKeyframe.m_isKeyframe) {
35 int kIndex = m_param->getClosestKeyframe(oldKeyframe.m_frame);
36 assert(0 <= kIndex && kIndex < m_param->getKeyframeCount());
37 assert(m_param->keyframeIndexToFrame(kIndex) == oldKeyframe.m_frame);
38 return kIndex;
39 }
40 m_param->setKeyframe(oldKeyframe);
41 int kIndex = m_param->getClosestKeyframe(oldKeyframe.m_frame);
42 assert(0 <= kIndex && kIndex < m_param->getKeyframeCount());
43 assert(m_param->keyframeIndexToFrame(kIndex) == oldKeyframe.m_frame);
44 assert(m_oldKeyframes.count(kIndex) == 0);
45 m_oldKeyframes[kIndex] = oldKeyframe;
46 return kIndex;
47 }
48
onAdd()49 void onAdd() override {
50 Keyframes::iterator it;
51 for (it = m_oldKeyframes.begin(); it != m_oldKeyframes.end(); ++it) {
52 int kIndex = it->first;
53 assert(0 <= kIndex && kIndex < m_param->getKeyframeCount());
54 m_newKeyframes[kIndex] = m_param->getKeyframe(kIndex);
55 }
56 }
undo() const57 void undo() const override {
58 m_param->setKeyframes(m_oldKeyframes);
59 Keyframes::const_iterator it;
60 for (it = m_oldKeyframes.begin(); it != m_oldKeyframes.end(); ++it)
61 if (!it->second.m_isKeyframe) m_param->deleteKeyframe(it->second.m_frame);
62 }
redo() const63 void redo() const override {
64 Keyframes::const_iterator it;
65 for (it = m_oldKeyframes.begin(); it != m_oldKeyframes.end(); ++it)
66 if (!it->second.m_isKeyframe) m_param->setKeyframe(it->second);
67 m_param->setKeyframes(m_newKeyframes);
68 }
getSize() const69 int getSize() const override {
70 return sizeof(*this) +
71 sizeof(*m_oldKeyframes.begin()) * 2 * m_oldKeyframes.size();
72 }
getHistoryString()73 QString getHistoryString() override { return QObject::tr("Set Keyframe"); }
74 };
75
76 //=============================================================================
77 //
78 // KeyframeSetter
79 //
80 //-----------------------------------------------------------------------------
81
KeyframeSetter(TDoubleParam * param,int kIndex,bool enableUndo)82 KeyframeSetter::KeyframeSetter(TDoubleParam *param, int kIndex, bool enableUndo)
83 : m_param(param)
84 , m_kIndex(-1)
85 , m_extraDFrame(0)
86 , m_enableUndo(enableUndo)
87 , m_undo(new KeyframesUndo(param))
88 , m_changed(false)
89 , m_pixelRatio(1) {
90 if (kIndex >= 0) selectKeyframe(kIndex);
91 }
92
~KeyframeSetter()93 KeyframeSetter::~KeyframeSetter() {
94 if (m_enableUndo)
95 addUndo();
96 else if (m_undo) {
97 delete m_undo;
98 m_undo = 0;
99 }
100 }
101
addUndo()102 void KeyframeSetter::addUndo() {
103 if (m_undo) {
104 if (m_changed)
105 TUndoManager::manager()->add(m_undo);
106 else
107 delete m_undo;
108 m_undo = 0;
109 }
110 }
111
selectKeyframe(int kIndex)112 void KeyframeSetter::selectKeyframe(int kIndex) {
113 if (m_indices.count(kIndex) == 0) {
114 m_indices.insert(kIndex);
115 m_undo->addKeyframe(kIndex);
116 }
117 m_kIndex = kIndex;
118 m_keyframe = m_param->getKeyframe(m_kIndex);
119 }
120
121 // set key frame at frame and returns its index
createKeyframe(double frame)122 int KeyframeSetter::createKeyframe(double frame) {
123 /*--- すでにそこにキーフレームがある場合はそのIndexを返すだけ ---*/
124 int kIndex = m_param->getClosestKeyframe(frame);
125 if (kIndex >= 0 && m_param->getKeyframe(kIndex).m_frame == frame) {
126 selectKeyframe(kIndex);
127 return kIndex;
128 }
129 m_changed = true;
130 kIndex = m_undo->createKeyframe(frame);
131 m_indices.insert(kIndex);
132 m_kIndex = kIndex;
133 m_keyframe = m_param->getKeyframe(m_kIndex);
134
135 setStep(Preferences::instance()->getAnimationStep());
136
137 int kCount = m_param->getKeyframeCount();
138 if (kCount <= 1) {
139 // a single keyframe created in a empty curve
140 } else if (kCount == 2) {
141 // two keyframes => a linear segment
142 TDoubleKeyframe::Type type =
143 TDoubleKeyframe::Type(Preferences::instance()->getKeyframeType());
144 setType(0, type);
145 } else {
146 // there are at least other two keyframes (and therefore at least a segment)
147 if (m_kIndex == 0) {
148 // a new segment added before the others. use the preference value
149 setType(
150 TDoubleKeyframe::Type(Preferences::instance()->getKeyframeType()));
151 } else if (m_kIndex == kCount - 1) {
152 // a new segment added after the others. use the preference value too
153 setType(m_kIndex - 1, TDoubleKeyframe::Type(
154 Preferences::instance()->getKeyframeType()));
155 } else {
156 // a new point in a segment
157 TDoubleKeyframe ka = m_param->getKeyframe(m_kIndex - 1);
158 TDoubleKeyframe kb = m_param->getKeyframe(m_kIndex + 1);
159 TDoubleKeyframe::Type segmentType = ka.m_type;
160 m_keyframe.m_type = ka.m_type;
161 m_keyframe.m_step = ka.m_step; // An existing segment step should prevail
162 // over the preference
163
164 /*---Segment内にKeyを打った場合は、Step値も元のSegmentの値を引き継ぐようにする---*/
165 m_param->setKeyframe(m_kIndex, m_keyframe);
166
167 if (segmentType == TDoubleKeyframe::SpeedInOut ||
168 segmentType == TDoubleKeyframe::EaseInOut ||
169 segmentType == TDoubleKeyframe::EaseInOutPercentage) {
170 std::map<int, TDoubleKeyframe> keyframes;
171 if (segmentType == TDoubleKeyframe::SpeedInOut) {
172 splitSpeedInOutSegment(m_keyframe, ka, kb);
173 } else if (segmentType == TDoubleKeyframe::EaseInOut) {
174 m_keyframe.m_speedIn = m_keyframe.m_speedOut = TPointD();
175 if (ka.m_frame + ka.m_speedOut.x > m_keyframe.m_frame)
176 ka.m_speedOut.x = m_keyframe.m_frame - ka.m_frame;
177 if (kb.m_frame + kb.m_speedIn.x < m_keyframe.m_frame)
178 ka.m_speedIn.x = m_keyframe.m_frame - kb.m_frame;
179 } else // easeinpercentage
180 {
181 m_keyframe.m_speedIn = m_keyframe.m_speedOut = TPointD();
182 double segmentWidth = kb.m_frame - ka.m_frame;
183 }
184 keyframes[m_kIndex - 1] = ka;
185 keyframes[m_kIndex] = m_keyframe;
186 keyframes[m_kIndex + 1] = kb;
187 m_undo->addKeyframe(m_kIndex - 1);
188 m_undo->addKeyframe(m_kIndex + 1);
189 m_param->setKeyframes(keyframes);
190 } else if (segmentType == TDoubleKeyframe::Expression ||
191 segmentType == TDoubleKeyframe::SimilarShape) {
192 std::string expressionText = ka.m_expressionText;
193
194 setExpression(expressionText);
195 setType(ka.m_type);
196 } else
197 setType(ka.m_type);
198 }
199 }
200 return kIndex;
201 }
202
isSpeedInOut(int segmentIndex) const203 bool KeyframeSetter::isSpeedInOut(int segmentIndex) const {
204 return 0 <= segmentIndex && segmentIndex + 1 < m_param->getKeyframeCount() &&
205 m_param->getKeyframe(segmentIndex).m_type ==
206 TDoubleKeyframe::SpeedInOut;
207 }
208
isEaseInOut(int segmentIndex) const209 bool KeyframeSetter::isEaseInOut(int segmentIndex) const {
210 if (0 <= segmentIndex && segmentIndex + 1 < m_param->getKeyframeCount()) {
211 TDoubleKeyframe::Type type = m_param->getKeyframe(segmentIndex).m_type;
212 if (type == TDoubleKeyframe::EaseInOut ||
213 type == TDoubleKeyframe::EaseInOutPercentage)
214 return true;
215 }
216 return false;
217 }
218
219 // find the speedInOut handles which will change when moving keyframe kIndex
220 // rotatingSpeeds: { <speed, keyframe index> }
getRotatingSpeedHandles(std::vector<std::pair<double,int>> & rotatingSpeeds,TDoubleParam * param,int kIndex) const221 void KeyframeSetter::getRotatingSpeedHandles(
222 std::vector<std::pair<double, int>> &rotatingSpeeds, TDoubleParam *param,
223 int kIndex) const {
224 const double epsilon = 1.0e-7;
225 int ty[4] = {0, 0, 0, 0};
226 // ty[] refers to segments around the kIndex keyframe
227 // 1 ==> linear or exponential (they can cause speed handle rotation)
228 // 2 ==> speedinout
229 for (int i = 0; i < 4; i++) {
230 int k = kIndex + i - 2;
231 if (0 <= k && k < param->getKeyframeCount()) {
232 TDoubleKeyframe::Type type = param->getKeyframe(k).m_type;
233 if (type == TDoubleKeyframe::Linear ||
234 type == TDoubleKeyframe::Exponential)
235 ty[i] = 1;
236 else if (type == TDoubleKeyframe::SpeedInOut)
237 ty[i] = 2;
238 }
239 }
240 // SpeedInOut * Linear *
241 if ((ty[0] == 2 && ty[1] == 1) || (ty[1] == 2 && ty[2] == 1)) {
242 int k = ty[1] == 1 ? kIndex - 1 : kIndex;
243 double speed = getNorm(param->getSpeedIn(k));
244 if (speed > epsilon) rotatingSpeeds.push_back(std::make_pair(-speed, k));
245 }
246 // * Linear * SpeedInOut
247 if ((ty[1] == 1 && ty[2] == 2) || (ty[2] == 1 && ty[3] == 2)) {
248 int k = ty[2] == 2 ? kIndex : kIndex + 1;
249 double speed = getNorm(param->getSpeedOut(k));
250 if (speed > epsilon) rotatingSpeeds.push_back(std::make_pair(speed, k));
251 }
252 }
253
moveKeyframes(int dFrame,double dValue)254 void KeyframeSetter::moveKeyframes(int dFrame, double dValue) {
255 int n = m_param->getKeyframeCount();
256 if (n == 0) return;
257
258 // to keep constant the "length" of speed handles which are modified as side
259 // effects
260 std::vector<std::pair<double, int>> rotatingSpeedHandles;
261 if (m_indices.size() == 1)
262 getRotatingSpeedHandles(rotatingSpeedHandles, m_param.getPointer(),
263 *m_indices.begin());
264
265 // update the frame change (m_extraDFrame represent old moves
266 // which has not performed, e.g. because of keyframe collisions)
267 dFrame += m_extraDFrame;
268 m_extraDFrame = 0;
269
270 if (dFrame != 0) {
271 // check frame constraints (keyframe collisions and segment type swaps)
272 double preferredDFrame = dFrame;
273 double dFrameSgn = dFrame < 0 ? -1 : 1;
274 dFrame *= dFrameSgn;
275
276 typedef std::pair<TDoubleKeyframe::Type, TDoubleKeyframe::Type> TypePair;
277 std::vector<std::pair<double, TypePair>> keyframes(n);
278 keyframes[0].second.first = TDoubleKeyframe::None;
279 for (int i = 0; i < n; i++) {
280 TDoubleKeyframe kf = m_param->getKeyframe(i);
281 keyframes[i].first = kf.m_frame;
282 if (i < n - 1) {
283 keyframes[i].second.second = kf.m_type;
284 keyframes[i + 1].second.first = kf.m_type;
285 } else
286 keyframes[i].second.second = TDoubleKeyframe::None;
287 }
288
289 while (dFrame > 0) {
290 std::vector<std::pair<double, TypePair>> mk(
291 keyframes); // mk = moved keyframes
292 std::set<int>::iterator it;
293 for (it = m_indices.begin(); it != m_indices.end(); ++it)
294 mk[*it].first += dFrame * dFrameSgn;
295 std::sort(mk.begin(), mk.end());
296 bool ok = true;
297 int i;
298 for (i = 0; i + 1 < n && ok; i++) {
299 // check keyframe collisions
300 if (fabs(mk[i + 1].first - mk[i].first) < 1.e-8) ok = false;
301 // check segment type swaps
302 if (mk[i].second.second != mk[i + 1].second.first &&
303 mk[i].second.second != TDoubleKeyframe::None &&
304 mk[i + 1].second.first != TDoubleKeyframe::None)
305 ok = false;
306 }
307 if (ok) break;
308 dFrame -= 1;
309 }
310
311 dFrame = dFrameSgn * std::max(0, dFrame);
312 if (dFrame != preferredDFrame) m_extraDFrame = preferredDFrame - dFrame;
313 // at this point dFrame (possibly ==0) is ok (no keyframe collisions, no
314 // segment type mismatches)
315 }
316
317 std::map<int, TDoubleKeyframe> change;
318 if (dFrame == 0) {
319 // only value changes
320
321 std::set<int>::iterator it;
322 int i = 0;
323 m_changed = true;
324 for (it = m_indices.begin(); it != m_indices.end(); ++it, i++) {
325 TDoubleKeyframe keyframe = m_param->getKeyframe(*it);
326 keyframe.m_value += dValue;
327 change[*it] = keyframe;
328 m_undo->addKeyframe(i);
329 }
330 } else {
331 // frame+value changes
332
333 int n = m_param->getKeyframeCount();
334 std::vector<std::pair<TDoubleKeyframe, int>> keyframes(
335 n); // (keyframe, index)
336 for (int i = 0; i < n; i++)
337 keyframes[i] = std::make_pair(m_param->getKeyframe(i), i);
338
339 // change frame and value of selected keyframes
340 std::set<int>::iterator it;
341 for (it = m_indices.begin(); it != m_indices.end(); ++it) {
342 int i = *it;
343 keyframes[i].first.m_frame += dFrame;
344 keyframes[i].first.m_value += dValue;
345 // keyframes[i].second = -1; // to mark keyframes involved in the move
346 }
347 // keyframes.back().first.m_type = TDoubleKeyframe::None;
348
349 // clear selection (indices can change: we have to rebuild it)
350
351 std::set<int> oldSelection(m_indices);
352 m_indices.clear();
353
354 // sort keyframes (according to their - updated - frames)
355 std::sort(keyframes.begin(), keyframes.end());
356
357 for (std::set<int>::iterator it = oldSelection.begin();
358 it != oldSelection.end(); ++it)
359 m_indices.insert(keyframes[*it].second);
360
361 // update segment types (because of swaps)
362 /*
363 for(int i=0;i+1<n;i++)
364 {
365 TDoubleKeyframe &kfa = keyframes[i].first;
366 TDoubleKeyframe &kfb = keyframes[i+1].first;
367 if(kfa.m_type == TDoubleKeyframe::None)
368 {
369 kfa.m_type = TDoubleKeyframe::SpeedInOut;
370 kfa.m_speedOut = TPointD(0,0);
371 }
372 if(kfb.m_prevType == TDoubleKeyframe::None)
373 {
374 kfa.m_prevType = TDoubleKeyframe::SpeedInOut;
375 kfa.m_speedIn = TPointD(0,0);
376 }
377 }
378 */
379
380 m_changed = true;
381 for (int i = 0; i < n; i++) {
382 if (keyframes[i].second != i) {
383 /*
384 // i-th keyframe has changed is order position
385 if(keyframes[i].first.m_type == TDoubleKeyframe::None)
386 {
387 if(i==n-1) keyframes[i].first.m_type = TDoubleKeyframe::Linear;
388 else keyframes[i].first.m_type = keyframes[i+1].first.m_type;
389 }
390 */
391
392 m_undo->addKeyframe(i);
393 change[i] = keyframes[i].first;
394 } else if (m_indices.count(i) > 0)
395 change[i] = keyframes[i].first;
396 }
397 }
398 m_param->setKeyframes(change);
399 /*
400 if(!rotatingSpeedHandles.empty())
401 {
402 for(int i=0;i<(int)rotatingSpeedHandles.size();i++)
403 {
404 double speedLength = rotatingSpeedHandles[i].first;
405 int kIndex = rotatingSpeedHandles[i].second;
406 TDoubleKeyframe kf = m_param->getKeyframe(kIndex);
407 TPointD speed = speedLength<0 ? m_param->getSpeedIn(kIndex) :
408 m_param->getSpeedOut(kIndex);
409 speed = fabs(speedLength/getNorm(speed)) * speed;
410 if(speedLength<0)
411 kf.m_speedIn = speed;
412 else
413 kf.m_speedOut = speed;
414 m_param->setKeyframe(kf);
415 }
416 }
417 */
418 }
419
setType(int kIndex,TDoubleKeyframe::Type type)420 void KeyframeSetter::setType(int kIndex, TDoubleKeyframe::Type type) {
421 assert(0 <= kIndex && kIndex < m_param->getKeyframeCount());
422 // get the current keyframe value
423 TDoubleKeyframe keyframe = m_param->getKeyframe(kIndex);
424 // get the next keyframe (if any) and compute the segment length
425 TDoubleKeyframe nextKeyframe;
426 double segmentWidth = 1;
427 if (kIndex + 1 < m_param->getKeyframeCount()) {
428 nextKeyframe = m_param->getKeyframe(kIndex + 1);
429 segmentWidth = nextKeyframe.m_frame - keyframe.m_frame;
430 } else if (kIndex + 1 > m_param->getKeyframeCount()) {
431 // kIndex is the last keyframe. no segment is defined (therefore no segment
432 // type)
433 type = TDoubleKeyframe::Linear;
434 }
435 if (type == keyframe.m_type) return;
436
437 // I'm going to change kIndex. Make sure it is selected. set the dirty flag
438 m_undo->addKeyframe(kIndex);
439 // m_indices.insert(kIndex);
440 m_changed = true;
441 double ease0 = 0, ease1 = 0;
442
443 std::map<int, TDoubleKeyframe> keyframes;
444 switch (type) {
445 case TDoubleKeyframe::SpeedInOut:
446 keyframe.m_speedOut = TPointD(segmentWidth / 3, 0);
447 nextKeyframe.m_speedIn = TPointD(-segmentWidth / 3, 0);
448 if (nextKeyframe.m_linkedHandles && nextKeyframe.m_speedOut.x > 0.01)
449 nextKeyframe.m_speedIn = -nextKeyframe.m_speedOut;
450 if (keyframe.m_linkedHandles && keyframe.m_speedIn.x < -0.01)
451 keyframe.m_speedOut = -keyframe.m_speedIn;
452 keyframe.m_type = type;
453 keyframes[kIndex] = keyframe;
454 keyframes[kIndex + 1] = nextKeyframe;
455 m_param->setKeyframes(keyframes);
456 break;
457
458 case TDoubleKeyframe::EaseInOut:
459 case TDoubleKeyframe::EaseInOutPercentage:
460 if (keyframe.m_type == TDoubleKeyframe::EaseInOut) {
461 // absolute -> percentage
462 ease0 = keyframe.m_speedOut.x * 100.0 / segmentWidth;
463 ease1 = -nextKeyframe.m_speedIn.x * 100.0 / segmentWidth;
464 // rounding could break constraints. crop parameters
465 ease0 = tcrop(ease0, 0.0, 100.0);
466 ease1 = tcrop(ease1, 0.0, 100.0 - ease0);
467 } else if (keyframe.m_type == TDoubleKeyframe::EaseInOutPercentage) {
468 // percentage -> absolute
469 ease0 = keyframe.m_speedOut.x * 0.01 * segmentWidth;
470 ease1 = -nextKeyframe.m_speedIn.x * 0.01 * segmentWidth;
471 // rounding could break constraints. crop parameters
472 ease0 = tcrop(ease0, 0.0, segmentWidth);
473 ease1 = tcrop(ease1, 0.0, segmentWidth - ease0);
474 } else {
475 ease1 = ease0 = segmentWidth / 3;
476 }
477 keyframe.m_speedOut = TPointD(ease0, 0);
478 nextKeyframe.m_speedIn = TPointD(-ease1, 0);
479
480 keyframe.m_type = type;
481 keyframes[kIndex] = keyframe;
482 keyframes[kIndex + 1] = nextKeyframe;
483 m_param->setKeyframes(keyframes);
484 break;
485
486 case TDoubleKeyframe::Expression:
487 keyframe.m_type = type;
488 {
489 double value = m_param->getValue(keyframe.m_frame);
490 const TUnit *unit = 0;
491 if (m_param->getMeasure()) unit = m_param->getMeasure()->getCurrentUnit();
492 if (unit) value = unit->convertTo(value);
493 keyframe.m_expressionText = QString::number(value).toStdString();
494 }
495 m_param->setKeyframe(kIndex, keyframe);
496 break;
497
498 default:
499 keyframe.m_type = type;
500 m_param->setKeyframe(kIndex, keyframe);
501 }
502 }
503
setType(TDoubleKeyframe::Type type)504 void KeyframeSetter::setType(TDoubleKeyframe::Type type) {
505 assert(m_kIndex >= 0 && m_indices.size() == 1);
506 setType(m_kIndex, type);
507 }
508
setStep(int step)509 void KeyframeSetter::setStep(int step) {
510 assert(m_kIndex >= 0 && m_indices.size() == 1);
511 if (m_keyframe.m_step == step) return;
512 m_changed = true;
513 m_keyframe.m_step = step;
514 m_param->setKeyframe(m_kIndex, m_keyframe);
515 }
516
setExpression(std::string expression)517 void KeyframeSetter::setExpression(std::string expression) {
518 assert(m_kIndex >= 0 && m_indices.size() == 1);
519 m_changed = true;
520 m_keyframe.m_expressionText = expression;
521 m_keyframe.m_type = TDoubleKeyframe::Expression;
522 m_param->setKeyframe(m_kIndex, m_keyframe);
523 }
524
setSimilarShape(std::string expression,double offset)525 void KeyframeSetter::setSimilarShape(std::string expression, double offset) {
526 assert(m_kIndex >= 0 && m_indices.size() == 1);
527 m_changed = true;
528 m_keyframe.m_expressionText = expression;
529 m_keyframe.m_similarShapeOffset = offset;
530 m_keyframe.m_type = TDoubleKeyframe::SimilarShape;
531 m_param->setKeyframe(m_kIndex, m_keyframe);
532 }
533
setFile(const TDoubleKeyframe::FileParams & params)534 void KeyframeSetter::setFile(const TDoubleKeyframe::FileParams ¶ms) {
535 assert(m_kIndex >= 0 && m_indices.size() == 1);
536 m_changed = true;
537 m_keyframe.m_fileParams = params;
538 m_keyframe.m_type = TDoubleKeyframe::File;
539 m_param->setKeyframe(m_kIndex, m_keyframe);
540 }
541
setUnitName(std::string unitName)542 void KeyframeSetter::setUnitName(std::string unitName) {
543 assert(m_kIndex >= 0 && m_indices.size() == 1);
544 m_changed = true;
545 m_keyframe.m_unitName = unitName;
546 m_param->setKeyframe(m_kIndex, m_keyframe);
547 }
548
setValue(double value)549 void KeyframeSetter::setValue(double value) {
550 assert(m_kIndex >= 0 && m_indices.size() == 1);
551 if (m_keyframe.m_value == value) return;
552 m_changed = true;
553 m_keyframe.m_value = value;
554 m_param->setKeyframe(m_kIndex, m_keyframe);
555 }
556
linkHandles()557 void KeyframeSetter::linkHandles() {
558 assert(m_kIndex >= 0 && m_indices.size() == 1);
559 if (m_keyframe.m_linkedHandles) return;
560 m_changed = true;
561 m_keyframe.m_linkedHandles = true;
562 if (isSpeedInOut(m_kIndex) && isSpeedInOut(m_kIndex - 1)) {
563 // keyframe is between two speedin/out segments (and therefore linkHandles
564 // makes sense)
565 TPointD d = -m_keyframe.m_speedIn + m_keyframe.m_speedOut;
566 const double eps = 0.1e-3;
567 if (d.x <= eps) {
568 m_keyframe.m_speedIn = m_keyframe.m_speedOut = TPointD(0, 0);
569 } else {
570 m_keyframe.m_speedIn.y = d.y * m_keyframe.m_speedIn.x / d.x;
571 m_keyframe.m_speedOut.y = d.y * m_keyframe.m_speedOut.x / d.x;
572 }
573 }
574 m_param->setKeyframe(m_kIndex, m_keyframe);
575 }
576
unlinkHandles()577 void KeyframeSetter::unlinkHandles() {
578 assert(m_kIndex >= 0 && m_indices.size() == 1);
579 if (!m_keyframe.m_linkedHandles) return;
580 m_changed = true;
581 m_keyframe.m_linkedHandles = false;
582 m_param->setKeyframe(m_kIndex, m_keyframe);
583 }
584
setSpeedIn(const TPointD & speedIn)585 void KeyframeSetter::setSpeedIn(const TPointD &speedIn) {
586 const double eps = 0.00001;
587 assert(m_kIndex >= 0 && m_indices.size() == 1);
588 assert(isSpeedInOut(m_kIndex - 1));
589 m_changed = true;
590 m_keyframe.m_speedIn = speedIn;
591 if (m_keyframe.m_speedIn.x > 0) m_keyframe.m_speedIn.x = 0;
592 if (m_keyframe.m_linkedHandles &&
593 m_kIndex + 1 <= m_param->getKeyframeCount()) {
594 double outNorm = getNorm(m_keyframe.m_speedOut);
595 if (m_kIndex + 1 == m_param->getKeyframeCount() || isSpeedInOut(m_kIndex) ||
596 (m_keyframe.m_type == TDoubleKeyframe::Expression &&
597 m_keyframe.m_expressionText.find("cycle") != std::string::npos)) {
598 // update next segment speed vector
599 double inNorm = getNorm(m_keyframe.m_speedIn);
600 if (inNorm < eps)
601 m_keyframe.m_speedOut = TPointD(outNorm, 0);
602 else
603 m_keyframe.m_speedOut = -(outNorm / inNorm) * m_keyframe.m_speedIn;
604 } else {
605 // can't change next segment speed vector => adjust speedIn to be
606 // collinear
607 TPointD w = rotate90(m_keyframe.m_speedOut);
608 double wNorm2 = norm2(w);
609 if (wNorm2 > eps * eps)
610 m_keyframe.m_speedIn -= (1.0 / wNorm2) * (w * m_keyframe.m_speedIn) * w;
611 }
612 }
613 m_param->setKeyframe(m_kIndex, m_keyframe);
614 }
615
setSpeedOut(const TPointD & speedOut)616 void KeyframeSetter::setSpeedOut(const TPointD &speedOut) {
617 const double eps = 0.00001;
618 assert(m_kIndex >= 0 && m_indices.size() == 1);
619 assert(isSpeedInOut(m_kIndex));
620 m_changed = true;
621 m_keyframe.m_speedOut = speedOut;
622 if (m_keyframe.m_speedOut.x < 0) m_keyframe.m_speedOut.x = 0;
623 if (m_keyframe.m_linkedHandles && m_kIndex > 0) {
624 double inNorm = getNorm(m_keyframe.m_speedIn);
625 if (isSpeedInOut(m_kIndex - 1)) {
626 // update previous segment speed vector
627 double outNorm = getNorm(m_keyframe.m_speedOut);
628 if (outNorm > eps)
629 m_keyframe.m_speedIn = -inNorm / outNorm * m_keyframe.m_speedOut;
630 // else
631 // m_keyframe.m_speedIn = TPointD(inNorm,0);
632
633 } else {
634 // can't change previous segment speed vector => adjust speedOut to be
635 // collinear
636 double h = 0.00001;
637 double f = m_keyframe.m_frame;
638 double v = (m_param->getValue(f) - m_param->getValue(f - h)) / h;
639 TPointD w(-v, 1);
640 double wNorm2 = norm2(w);
641 if (wNorm2 > eps * eps)
642 m_keyframe.m_speedOut -=
643 (1.0 / wNorm2) * (w * m_keyframe.m_speedOut) * w;
644 }
645 }
646 m_param->setKeyframe(m_kIndex, m_keyframe);
647 }
648
setEaseIn(double easeIn)649 void KeyframeSetter::setEaseIn(double easeIn) {
650 // easeIn <=0
651 assert(m_kIndex >= 1 && m_indices.size() == 1);
652 assert(isEaseInOut(m_kIndex - 1));
653 m_changed = true;
654 TDoubleKeyframe prevKeyframe = m_param->getKeyframe(m_kIndex - 1);
655 bool isPercentage =
656 prevKeyframe.m_type == TDoubleKeyframe::EaseInOutPercentage;
657 if (!isPercentage) easeIn = floor(easeIn + 0.5);
658 double segmentWidth =
659 isPercentage ? 100.0 : m_keyframe.m_frame - prevKeyframe.m_frame;
660 easeIn = -tcrop(-easeIn, 0.0, segmentWidth);
661 m_keyframe.m_speedIn = TPointD(easeIn, 0);
662 if (prevKeyframe.m_speedOut.x - easeIn > segmentWidth) {
663 m_undo->addKeyframe(m_kIndex - 1);
664 prevKeyframe.m_speedOut.x = segmentWidth + easeIn;
665 std::map<int, TDoubleKeyframe> keyframes;
666 keyframes[m_kIndex - 1] = prevKeyframe;
667 keyframes[m_kIndex] = m_keyframe;
668 m_param->setKeyframes(keyframes);
669 } else {
670 m_param->setKeyframe(m_kIndex, m_keyframe);
671 }
672 }
673
setEaseOut(double easeOut)674 void KeyframeSetter::setEaseOut(double easeOut) {
675 assert(m_kIndex >= 0 && m_kIndex + 1 < m_param->getKeyframeCount() &&
676 m_indices.size() == 1);
677 assert(isEaseInOut(m_kIndex));
678 m_changed = true;
679 TDoubleKeyframe nextKeyframe = m_param->getKeyframe(m_kIndex + 1);
680 bool isPercentage = m_keyframe.m_type == TDoubleKeyframe::EaseInOutPercentage;
681 if (!isPercentage) easeOut = floor(easeOut + 0.5);
682 double segmentWidth =
683 isPercentage ? 100.0 : nextKeyframe.m_frame - m_keyframe.m_frame;
684 easeOut = tcrop(easeOut, 0.0, segmentWidth);
685 m_keyframe.m_speedOut = TPointD(easeOut, 0);
686 if (-nextKeyframe.m_speedIn.x + easeOut > segmentWidth) {
687 m_undo->addKeyframe(m_kIndex + 1);
688 nextKeyframe.m_speedIn.x = easeOut - segmentWidth;
689 std::map<int, TDoubleKeyframe> keyframes;
690 keyframes[m_kIndex + 1] = nextKeyframe;
691 keyframes[m_kIndex] = m_keyframe;
692 m_param->setKeyframes(keyframes);
693 } else {
694 m_param->setKeyframe(m_kIndex, m_keyframe);
695 }
696 }
697
698 //=============================================================================
699
700 // set the curve params adaptively by clicking apply button
setAllParams(int step,TDoubleKeyframe::Type comboType,const TPointD & speedIn,const TPointD & speedOut,std::string expressionText,std::string unitName,const TDoubleKeyframe::FileParams & fileParam,double similarShapeOffset)701 void KeyframeSetter::setAllParams(
702 int step, TDoubleKeyframe::Type comboType, const TPointD &speedIn,
703 const TPointD &speedOut, std::string expressionText, std::string unitName,
704 const TDoubleKeyframe::FileParams &fileParam, double similarShapeOffset) {
705 assert(0 <= m_kIndex && m_kIndex < m_param->getKeyframeCount());
706
707 TDoubleKeyframe keyframe = m_param->getKeyframe(m_kIndex);
708 TDoubleKeyframe nextKeyframe;
709
710 // get the next key
711 if (m_kIndex + 1 < m_param->getKeyframeCount())
712 nextKeyframe = m_param->getKeyframe(m_kIndex + 1);
713 else
714 comboType = TDoubleKeyframe::Linear;
715
716 // I'm going to change kIndex. Make sure it is selected. set the dirty flag
717 m_undo->addKeyframe(m_kIndex);
718 m_indices.insert(m_kIndex);
719 m_changed = true;
720
721 // set step
722 if (step < 1) step = 1;
723 keyframe.m_step = step;
724
725 // set type
726 keyframe.m_type = comboType;
727
728 // set parameters according to the type
729 std::map<int, TDoubleKeyframe> keyframes;
730 switch (comboType) {
731 case TDoubleKeyframe::SpeedInOut:
732 keyframe.m_speedOut = speedOut;
733 nextKeyframe.m_speedIn = speedIn;
734
735 if (keyframe.m_speedOut.x < 0) keyframe.m_speedOut.x = 0;
736 if (nextKeyframe.m_speedIn.x > 0) nextKeyframe.m_speedIn.x = 0;
737 break;
738
739 case TDoubleKeyframe::EaseInOut:
740 case TDoubleKeyframe::EaseInOutPercentage:
741 keyframe.m_speedOut = speedOut;
742 nextKeyframe.m_speedIn = speedIn;
743 if (keyframe.m_type == TDoubleKeyframe::EaseInOut) {
744 keyframe.m_speedOut.x = floor(speedOut.x + 0.5);
745 nextKeyframe.m_speedIn.x = floor(speedIn.x + 0.5);
746 }
747 break;
748
749 case TDoubleKeyframe::Expression:
750 keyframe.m_expressionText = expressionText;
751 keyframe.m_unitName = unitName;
752 break;
753
754 case TDoubleKeyframe::File:
755 keyframe.m_fileParams = fileParam;
756 keyframe.m_unitName = unitName;
757 break;
758
759 case TDoubleKeyframe::SimilarShape:
760 keyframe.m_expressionText = expressionText;
761 keyframe.m_similarShapeOffset = similarShapeOffset;
762 break;
763
764 default:
765 break;
766 }
767
768 /*--- リンクされたカーブの処理 ---*/
769 const double eps = 0.00001;
770 if (m_kIndex != 0 && keyframe.m_linkedHandles &&
771 keyframe.m_prevType == TDoubleKeyframe::SpeedInOut) {
772 double inNorm = getNorm(keyframe.m_speedIn);
773 // update previous segment speed vector
774 double outNorm = getNorm(keyframe.m_speedOut);
775 if (outNorm > eps)
776 keyframe.m_speedIn = -inNorm / outNorm * keyframe.m_speedOut;
777 }
778
779 // Next curve
780 if (m_kIndex + 2 < m_param->getKeyframeCount() &&
781 nextKeyframe.m_linkedHandles &&
782 nextKeyframe.m_type == TDoubleKeyframe::SpeedInOut) {
783 double outNorm = getNorm(nextKeyframe.m_speedOut);
784 // update next segment speed vector
785 double inNorm = getNorm(nextKeyframe.m_speedIn);
786 if (inNorm < eps)
787 nextKeyframe.m_speedOut = TPointD(outNorm, 0);
788 else
789 nextKeyframe.m_speedOut = -(outNorm / inNorm) * nextKeyframe.m_speedIn;
790 }
791
792 // set modified keyframe
793 keyframes[m_kIndex] = keyframe;
794 if (m_kIndex + 1 < m_param->getKeyframeCount())
795 keyframes[m_kIndex + 1] = nextKeyframe;
796
797 m_param->setKeyframes(keyframes);
798 }
799
800 //=============================================================================
801
802 class RemoveKeyframeUndo final : public TUndo {
803 TDoubleParam *m_param;
804 TDoubleKeyframe m_keyframe;
805
806 public:
RemoveKeyframeUndo(TDoubleParam * param,int kIndex)807 RemoveKeyframeUndo(TDoubleParam *param, int kIndex) : m_param(param) {
808 m_param->addRef();
809 m_keyframe = m_param->getKeyframe(kIndex);
810 }
~RemoveKeyframeUndo()811 ~RemoveKeyframeUndo() { m_param->release(); }
undo() const812 void undo() const override { m_param->setKeyframe(m_keyframe); }
redo() const813 void redo() const override { m_param->deleteKeyframe(m_keyframe.m_frame); }
getSize() const814 int getSize() const override { return sizeof(*this); }
815
getHistoryString()816 QString getHistoryString() override { return QObject::tr("Remove Keyframe"); }
817 };
818
819 //=============================================================================
820
removeKeyframeAt(TDoubleParam * curve,double frame)821 void KeyframeSetter::removeKeyframeAt(TDoubleParam *curve, double frame) {
822 int kIndex = curve->getClosestKeyframe(frame);
823 if (kIndex < 0 || kIndex >= curve->getKeyframeCount() ||
824 curve->keyframeIndexToFrame(kIndex) != frame)
825 return;
826 TUndoManager::manager()->add(new RemoveKeyframeUndo(curve, kIndex));
827 curve->deleteKeyframe(frame);
828 }
829
830 //=============================================================================
831
832 class EnableCycleUndo final : public TUndo {
833 TDoubleParam *m_param;
834 TSceneHandle *m_sceneHandle;
835
836 public:
EnableCycleUndo(TDoubleParam * param,TSceneHandle * sceneHandle)837 EnableCycleUndo(TDoubleParam *param, TSceneHandle *sceneHandle)
838 : m_param(param), m_sceneHandle(sceneHandle) {
839 m_param->addRef();
840 }
~EnableCycleUndo()841 ~EnableCycleUndo() { m_param->release(); }
invertCycleEnabled() const842 void invertCycleEnabled() const {
843 bool isEnabled = m_param->isCycleEnabled();
844 m_param->enableCycle(!isEnabled);
845 // for now the scene handle is only available when RMB click in function
846 // sheet
847 if (m_sceneHandle) {
848 m_sceneHandle->setDirtyFlag(true);
849 m_sceneHandle->notifySceneChanged();
850 }
851 }
undo() const852 void undo() const override { invertCycleEnabled(); }
redo() const853 void redo() const override { invertCycleEnabled(); }
getSize() const854 int getSize() const override { return sizeof(*this); }
855
getHistoryString()856 QString getHistoryString() override { return QObject::tr("Cycle"); }
857 };
858
859 //=============================================================================
860
enableCycle(TDoubleParam * curve,bool enabled,TSceneHandle * sceneHandle)861 void KeyframeSetter::enableCycle(TDoubleParam *curve, bool enabled,
862 TSceneHandle *sceneHandle) {
863 curve->enableCycle(enabled);
864 if (sceneHandle) sceneHandle->notifySceneChanged();
865 TUndoManager::manager()->add(new EnableCycleUndo(curve, sceneHandle));
866 }
867