Fix copy-paste keyframe interpolation (#2647)
This commit is contained in:
parent
567be0a394
commit
99f8f66143
1 changed files with 68 additions and 0 deletions
|
@ -10,6 +10,7 @@
|
||||||
#include "toonz/tstageobjecttree.h"
|
#include "toonz/tstageobjecttree.h"
|
||||||
#include "toonz/tstageobjectkeyframe.h"
|
#include "toonz/tstageobjectkeyframe.h"
|
||||||
#include "toonz/txshcolumn.h"
|
#include "toonz/txshcolumn.h"
|
||||||
|
#include "toonz/preferences.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
@ -84,9 +85,20 @@ bool TKeyframeData::getKeyframes(std::set<Position> &positions,
|
||||||
std::set<TKeyframeSelection::Position>::iterator it2 = positions.begin();
|
std::set<TKeyframeSelection::Position>::iterator it2 = positions.begin();
|
||||||
int r0 = it2->first;
|
int r0 = it2->first;
|
||||||
int c0 = it2->second;
|
int c0 = it2->second;
|
||||||
|
std::map<int, int> firstRowCol, lastRowCol;
|
||||||
|
firstRowCol.insert(std::pair<int, int>(c0, r0));
|
||||||
|
lastRowCol.insert(std::pair<int, int>(c0, r0));
|
||||||
for (++it2; it2 != positions.end(); ++it2) {
|
for (++it2; it2 != positions.end(); ++it2) {
|
||||||
r0 = std::min(r0, it2->first);
|
r0 = std::min(r0, it2->first);
|
||||||
c0 = std::min(c0, it2->second);
|
c0 = std::min(c0, it2->second);
|
||||||
|
std::map<int, int>::iterator itF = firstRowCol.find(it2->second);
|
||||||
|
std::map<int, int>::iterator itL = lastRowCol.find(it2->second);
|
||||||
|
if (itF == firstRowCol.end())
|
||||||
|
firstRowCol.insert(std::pair<int, int>(it2->second, it2->first));
|
||||||
|
if (itL == lastRowCol.end())
|
||||||
|
lastRowCol.insert(std::pair<int, int>(it2->second, it2->first));
|
||||||
|
else
|
||||||
|
itL->second = c0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XsheetViewer *viewer = TApp::instance()->getCurrentXsheetViewer();
|
XsheetViewer *viewer = TApp::instance()->getCurrentXsheetViewer();
|
||||||
|
@ -109,7 +121,63 @@ bool TKeyframeData::getKeyframes(std::set<Position> &positions,
|
||||||
continue;
|
continue;
|
||||||
keyFrameChanged = true;
|
keyFrameChanged = true;
|
||||||
assert(pegbar);
|
assert(pegbar);
|
||||||
|
|
||||||
|
int kF, kL, kP, kN;
|
||||||
|
double e0, e1;
|
||||||
|
pegbar->getKeyframeRange(kF, kL);
|
||||||
pegbar->setKeyframeWithoutUndo(row, it->second);
|
pegbar->setKeyframeWithoutUndo(row, it->second);
|
||||||
|
|
||||||
|
std::map<int, int>::iterator itF = firstRowCol.find(col);
|
||||||
|
std::map<int, int>::iterator itL = lastRowCol.find(col);
|
||||||
|
TStageObject::Keyframe newKey = pegbar->getKeyframe(row);
|
||||||
|
// Process 1st key added in column
|
||||||
|
if (itF != firstRowCol.end() && itF->second == row) {
|
||||||
|
if (row > kL) {
|
||||||
|
// If new key was added after the existing last one, create new
|
||||||
|
// interpolation between them using preference setting
|
||||||
|
TStageObject::Keyframe prevKey = pegbar->getKeyframe(kL);
|
||||||
|
for (int i = 0; i < TStageObject::T_ChannelCount; i++) {
|
||||||
|
prevKey.m_channels[i].m_type =
|
||||||
|
TDoubleKeyframe::Type(Preferences::instance()->getKeyframeType());
|
||||||
|
newKey.m_channels[i].m_prevType = prevKey.m_channels[i].m_type;
|
||||||
|
}
|
||||||
|
pegbar->setKeyframeWithoutUndo(kL, prevKey);
|
||||||
|
pegbar->setKeyframeWithoutUndo(row, newKey);
|
||||||
|
} else if (row > kF) {
|
||||||
|
// If new key was added between existing keys, sync new key's previous
|
||||||
|
// interpolation to key just before it
|
||||||
|
if (!pegbar->getKeyframeSpan(row - 1, kP, e0, kN, e1)) kP = row - 1;
|
||||||
|
TStageObject::Keyframe prevKey = pegbar->getKeyframe(kP);
|
||||||
|
for (int i = 0; i < TStageObject::T_ChannelCount; i++) {
|
||||||
|
newKey.m_channels[i].m_prevType = prevKey.m_channels[i].m_type;
|
||||||
|
}
|
||||||
|
pegbar->setKeyframeWithoutUndo(row, newKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Process last key added in column
|
||||||
|
if (itL != lastRowCol.end() && itL->second == row) {
|
||||||
|
if (row < kF) {
|
||||||
|
// If new key was added before the existing 1st one, create new
|
||||||
|
// interpolation between them using preference setting
|
||||||
|
TStageObject::Keyframe nextKey = pegbar->getKeyframe(kF);
|
||||||
|
for (int i = 0; i < TStageObject::T_ChannelCount; i++) {
|
||||||
|
newKey.m_channels[i].m_type =
|
||||||
|
TDoubleKeyframe::Type(Preferences::instance()->getKeyframeType());
|
||||||
|
nextKey.m_channels[i].m_prevType = newKey.m_channels[i].m_type;
|
||||||
|
}
|
||||||
|
pegbar->setKeyframeWithoutUndo(row, newKey);
|
||||||
|
pegbar->setKeyframeWithoutUndo(kF, nextKey);
|
||||||
|
} else if (row < kL) {
|
||||||
|
// If new key was added between existing keys, sync new key to the next
|
||||||
|
// key's previous interpolation
|
||||||
|
if (!pegbar->getKeyframeSpan(row + 1, kP, e0, kN, e1)) kN = row + 1;
|
||||||
|
TStageObject::Keyframe nextKey = pegbar->getKeyframe(kN);
|
||||||
|
for (int i = 0; i < TStageObject::T_ChannelCount; i++) {
|
||||||
|
newKey.m_channels[i].m_type = nextKey.m_channels[i].m_prevType;
|
||||||
|
}
|
||||||
|
pegbar->setKeyframeWithoutUndo(row, newKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!keyFrameChanged) return false;
|
if (!keyFrameChanged) return false;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue