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 &params) {
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