|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "toonzqt/functionselection.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "toonzqt/dvdialog.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// TnzLib includes
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/doubleparamcmd.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tframehandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/txsheetexpr.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// TnzBase includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tdoubleparam.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tdoublekeyframe.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "texpression.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// TnzCore includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tcommon.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tundo.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Qt includes
|
|
Toshihiro Shimizu |
890ddd |
#include <qapplication></qapplication>
|
|
Toshihiro Shimizu |
890ddd |
#include <qmimedata></qmimedata>
|
|
Toshihiro Shimizu |
890ddd |
#include <qclipboard></qclipboard>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// Function clipboard operations undo
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
d1f6c4 |
class KeyframesCopyUndo final : public TUndo {
|
|
Shinya Kitaoka |
120a6e |
QMimeData *m_oldData, *m_newData;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
KeyframesCopyUndo(const QMimeData *oldData, const QMimeData *newData)
|
|
Shinya Kitaoka |
120a6e |
: m_oldData(cloneData(oldData)), m_newData(cloneData(newData)) {}
|
|
Shinya Kitaoka |
120a6e |
~KeyframesCopyUndo() {
|
|
Shinya Kitaoka |
120a6e |
delete m_oldData;
|
|
Shinya Kitaoka |
120a6e |
delete m_newData;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void undo() const override {
|
|
Shinya Kitaoka |
120a6e |
QApplication::clipboard()->setMimeData(cloneData(m_oldData));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
void redo() const override {
|
|
Shinya Kitaoka |
120a6e |
QApplication::clipboard()->setMimeData(cloneData(m_newData));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
int getSize() const override {
|
|
Shinya Kitaoka |
120a6e |
return sizeof(*this) + sizeof(QMimeData) * 2; // approx
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
QString getHistoryString() override { return QObject::tr("Copy Keyframe"); }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
d1f6c4 |
class KeyframesPasteUndo final : public TUndo {
|
|
Shinya Kitaoka |
120a6e |
struct Column {
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *m_param;
|
|
Shinya Kitaoka |
120a6e |
std::map<int, tdoublekeyframe=""> m_oldKeyframes;</int,>
|
|
Shinya Kitaoka |
120a6e |
std::set<double> m_created;</double>
|
|
Shinya Kitaoka |
120a6e |
};
|
|
Shinya Kitaoka |
120a6e |
std::vector<column> m_columns;</column>
|
|
Shinya Kitaoka |
120a6e |
FunctionKeyframesData *m_data;
|
|
Shinya Kitaoka |
120a6e |
double m_frame;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
KeyframesPasteUndo(std::vector<tdoubleparam *=""> ¶ms,</tdoubleparam>
|
|
Shinya Kitaoka |
120a6e |
const FunctionKeyframesData *data, double frame)
|
|
Shinya Kitaoka |
120a6e |
: m_data(dynamic_cast<functionkeyframesdata *="">(data->clone()))</functionkeyframesdata>
|
|
Shinya Kitaoka |
120a6e |
, m_frame(frame) {
|
|
Shinya Kitaoka |
120a6e |
assert((int)params.size() <= data->getColumnCount());
|
|
Shinya Kitaoka |
120a6e |
int columnCount = std::min((int)(params.size()), data->getColumnCount());
|
|
Shinya Kitaoka |
120a6e |
m_columns.resize(columnCount);
|
|
Shinya Kitaoka |
120a6e |
for (int col = 0; col < columnCount; col++) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *param = params[col];
|
|
Shinya Kitaoka |
120a6e |
m_columns[col].m_param = param;
|
|
Shinya Kitaoka |
120a6e |
param->addRef();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const FunctionKeyframesData::Keyframes &keyframes =
|
|
Shinya Kitaoka |
120a6e |
data->getKeyframes(col);
|
|
Shinya Kitaoka |
120a6e |
FunctionKeyframesData::Keyframes::const_iterator it;
|
|
Shinya Kitaoka |
120a6e |
for (it = keyframes.begin(); it != keyframes.end(); ++it) {
|
|
Shinya Kitaoka |
120a6e |
double f = it->m_frame + frame;
|
|
Shinya Kitaoka |
120a6e |
int k = param->getClosestKeyframe(f);
|
|
Shinya Kitaoka |
120a6e |
if (0 <= k && k < param->getKeyframeCount() &&
|
|
Shinya Kitaoka |
120a6e |
param->keyframeIndexToFrame(k) == f)
|
|
Shinya Kitaoka |
120a6e |
m_columns[col].m_oldKeyframes[k] = param->getKeyframe(k);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
m_columns[col].m_created.insert(f);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
~KeyframesPasteUndo() {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_columns.size(); i++)
|
|
Shinya Kitaoka |
120a6e |
m_columns[i].m_param->release();
|
|
Shinya Kitaoka |
120a6e |
delete m_data;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void undo() const override {
|
|
Shinya Kitaoka |
120a6e |
int columnCount = (int)m_columns.size();
|
|
Shinya Kitaoka |
120a6e |
for (int col = 0; col < columnCount; col++) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *param = m_columns[col].m_param;
|
|
Shinya Kitaoka |
120a6e |
for (std::set<double>::const_iterator it =</double>
|
|
Shinya Kitaoka |
120a6e |
m_columns[col].m_created.begin();
|
|
Shinya Kitaoka |
120a6e |
it != m_columns[col].m_created.end(); ++it)
|
|
Shinya Kitaoka |
120a6e |
param->deleteKeyframe(*it);
|
|
Shinya Kitaoka |
120a6e |
param->setKeyframes(m_columns[col].m_oldKeyframes);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
void redo() const override {
|
|
Shinya Kitaoka |
120a6e |
for (int col = 0; col < (int)m_columns.size(); col++) {
|
|
Shinya Kitaoka |
120a6e |
m_data->setData(col, m_columns[col].m_param, m_frame);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
int getSize() const override {
|
|
Shinya Kitaoka |
120a6e |
return sizeof(*this) + 100; // approx
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
QString getHistoryString() override {
|
|
Shinya Kitaoka |
120a6e |
return QObject::tr("Paste Keyframe at Frame : %1")
|
|
Shinya Kitaoka |
120a6e |
.arg(QString::number((int)m_frame + 1));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
d1f6c4 |
class KeyframesDeleteUndo final : public TUndo {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
struct ColumnKeyframes {
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *m_param;
|
|
Shinya Kitaoka |
120a6e |
std::vector<tdoublekeyframe> m_keyframes;</tdoublekeyframe>
|
|
Shinya Kitaoka |
120a6e |
};
|
|
Shinya Kitaoka |
120a6e |
struct Column {
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *m_param;
|
|
Shinya Kitaoka |
120a6e |
QSet<int> m_keyframes;</int>
|
|
Shinya Kitaoka |
120a6e |
};
|
|
Shinya Kitaoka |
120a6e |
KeyframesDeleteUndo(const std::vector<column> &columns) {</column>
|
|
Shinya Kitaoka |
120a6e |
m_columns.resize(columns.size());
|
|
Shinya Kitaoka |
120a6e |
for (int col = 0; col < (int)m_columns.size(); col++) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *param = columns[col].m_param;
|
|
Shinya Kitaoka |
120a6e |
m_columns[col].m_param = param;
|
|
Shinya Kitaoka |
120a6e |
if (!param) continue;
|
|
Shinya Kitaoka |
120a6e |
param->addRef();
|
|
Shinya Kitaoka |
120a6e |
const QSet<int> &keyframes = columns[col].m_keyframes;</int>
|
|
Shinya Kitaoka |
120a6e |
for (QSet<int>::const_iterator it = keyframes.begin();</int>
|
|
Shinya Kitaoka |
120a6e |
it != keyframes.end(); ++it)
|
|
Shinya Kitaoka |
120a6e |
m_columns[col].m_keyframes.push_back(param->getKeyframe(*it));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
~KeyframesDeleteUndo() {
|
|
Shinya Kitaoka |
120a6e |
for (int col = 0; col < (int)m_columns.size(); col++)
|
|
Shinya Kitaoka |
120a6e |
m_columns[col].m_param->release();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void undo() const override {
|
|
Shinya Kitaoka |
120a6e |
for (int col = 0; col < (int)m_columns.size(); col++)
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_columns[col].m_keyframes.size(); i++)
|
|
Shinya Kitaoka |
120a6e |
m_columns[col].m_param->setKeyframe(m_columns[col].m_keyframes[i]);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
void redo() const override {
|
|
Shinya Kitaoka |
120a6e |
for (int col = 0; col < (int)m_columns.size(); col++)
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_columns[col].m_keyframes.size(); i++)
|
|
Shinya Kitaoka |
120a6e |
m_columns[col].m_param->deleteKeyframe(
|
|
Shinya Kitaoka |
120a6e |
m_columns[col].m_keyframes[i].m_frame);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
int getSize() const override {
|
|
Shinya Kitaoka |
120a6e |
return sizeof(*this) +
|
|
Shinya Kitaoka |
120a6e |
sizeof(TDoubleKeyframe) * m_columns.size(); // sbagliato!
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
QString getHistoryString() override { return QObject::tr("Delete Keyframe"); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Shinya Kitaoka |
120a6e |
std::vector<columnkeyframes> m_columns;</columnkeyframes>
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
d1f6c4 |
class KeyframesMoveUndo final : public TUndo {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
KeyframesMoveUndo() {}
|
|
Shinya Kitaoka |
120a6e |
~KeyframesMoveUndo() {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_movements.size(); i++)
|
|
Shinya Kitaoka |
120a6e |
m_movements[i].m_param->release();
|
|
Shinya Kitaoka |
120a6e |
m_movements.clear();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void addMovement(TDoubleParam *param, int kIndex, double frameDelta) {
|
|
Shinya Kitaoka |
120a6e |
m_movements.push_back(KeyframeMovement(param, kIndex, frameDelta));
|
|
Shinya Kitaoka |
120a6e |
param->addRef();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void undo() const override {
|
|
Shinya Kitaoka |
120a6e |
for (int i = (int)m_movements.size() - 1; i >= 0; i--) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleKeyframe kf =
|
|
Shinya Kitaoka |
120a6e |
m_movements[i].m_param->getKeyframe(m_movements[i].m_kIndex);
|
|
Shinya Kitaoka |
120a6e |
kf.m_frame -= m_movements[i].m_frameDelta;
|
|
Shinya Kitaoka |
120a6e |
m_movements[i].m_param->setKeyframe(m_movements[i].m_kIndex, kf);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
void redo() const override {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_movements.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleKeyframe kf =
|
|
Shinya Kitaoka |
120a6e |
m_movements[i].m_param->getKeyframe(m_movements[i].m_kIndex);
|
|
Shinya Kitaoka |
120a6e |
kf.m_frame += m_movements[i].m_frameDelta;
|
|
Shinya Kitaoka |
120a6e |
m_movements[i].m_param->setKeyframe(m_movements[i].m_kIndex, kf);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
int getSize() const override {
|
|
Shinya Kitaoka |
120a6e |
return sizeof(*this) + sizeof(m_movements[0]) * m_movements.size();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
int getCount() const { return (int)m_movements.size(); }
|
|
Shinya Kitaoka |
473e70 |
QString getHistoryString() override { return QObject::tr("Move Keyframe"); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Shinya Kitaoka |
120a6e |
struct KeyframeMovement {
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *m_param;
|
|
Shinya Kitaoka |
120a6e |
int m_kIndex;
|
|
Shinya Kitaoka |
120a6e |
double m_frameDelta;
|
|
Shinya Kitaoka |
120a6e |
KeyframeMovement(TDoubleParam *param, int kIndex, double frameDelta)
|
|
Shinya Kitaoka |
120a6e |
: m_param(param), m_kIndex(kIndex), m_frameDelta(frameDelta) {}
|
|
Shinya Kitaoka |
120a6e |
};
|
|
Shinya Kitaoka |
120a6e |
std::vector<keyframemovement> m_movements;</keyframemovement>
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// FunctionSelection
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
FunctionSelection::FunctionSelection()
|
|
Shinya Kitaoka |
120a6e |
: m_selectedCells()
|
|
Shinya Kitaoka |
120a6e |
, m_selectedKeyframes()
|
|
Shinya Kitaoka |
120a6e |
, m_selectedSegment(-1)
|
|
Shinya Kitaoka |
120a6e |
, m_frameHandle(0)
|
|
Shinya Kitaoka |
120a6e |
, m_columnToCurveMapper(0) {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
FunctionSelection::~FunctionSelection() {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < m_selectedKeyframes.size(); i++)
|
|
Shinya Kitaoka |
120a6e |
if (m_selectedKeyframes[i].first) m_selectedKeyframes[i].first->release();
|
|
Shinya Kitaoka |
120a6e |
m_selectedKeyframes.clear();
|
|
Shinya Kitaoka |
120a6e |
delete m_columnToCurveMapper;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void FunctionSelection::setColumnToCurveMapper(ColumnToCurveMapper *mapper) {
|
|
Shinya Kitaoka |
120a6e |
if (mapper != m_columnToCurveMapper) {
|
|
Shinya Kitaoka |
120a6e |
delete m_columnToCurveMapper;
|
|
Shinya Kitaoka |
120a6e |
m_columnToCurveMapper = mapper;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void FunctionSelection::selectCurve(TDoubleParam *curve) {
|
|
Shinya Kitaoka |
120a6e |
if (m_selectedKeyframes.size() == 1 && m_selectedKeyframes[0].first == curve)
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
curve->addRef();
|
|
Shinya Kitaoka |
120a6e |
deselectAllKeyframes();
|
|
Shinya Kitaoka |
120a6e |
m_selectedKeyframes.push_back(qMakePair(curve, QSet<int>()));</int>
|
|
Shinya Kitaoka |
120a6e |
m_selectedCells = QRect();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void FunctionSelection::deselectAllKeyframes() {
|
|
Shinya Kitaoka |
120a6e |
if (getSelectedKeyframeCount() == 0) return;
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < m_selectedKeyframes.size(); i++)
|
|
Shinya Kitaoka |
120a6e |
m_selectedKeyframes[i].second.clear();
|
|
Shinya Kitaoka |
120a6e |
emit selectionChanged();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int FunctionSelection::getCurveIndex(TDoubleParam *curve) const {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < m_selectedKeyframes.size(); i++)
|
|
Shinya Kitaoka |
120a6e |
if (m_selectedKeyframes[i].first == curve) return i;
|
|
Shinya Kitaoka |
120a6e |
return -1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int FunctionSelection::touchCurveIndex(TDoubleParam *curve) {
|
|
Shinya Kitaoka |
120a6e |
int i = getCurveIndex(curve);
|
|
Shinya Kitaoka |
120a6e |
if (i < 0) {
|
|
Shinya Kitaoka |
120a6e |
i = m_selectedKeyframes.size();
|
|
Shinya Kitaoka |
120a6e |
m_selectedKeyframes.push_back(qMakePair(curve, QSet<int>()));</int>
|
|
Shinya Kitaoka |
120a6e |
curve->addRef();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return i;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void FunctionSelection::selectNone() {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < m_selectedKeyframes.size(); i++)
|
|
Shinya Kitaoka |
120a6e |
if (m_selectedKeyframes[i].first) m_selectedKeyframes[i].first->release();
|
|
Shinya Kitaoka |
120a6e |
m_selectedKeyframes.clear();
|
|
Shinya Kitaoka |
120a6e |
m_selectedSegment = -1;
|
|
Shinya Kitaoka |
120a6e |
m_selectedCells = QRect();
|
|
Shinya Kitaoka |
120a6e |
emit selectionChanged();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// called from FunctionSheet::selectCells
|
|
Shinya Kitaoka |
120a6e |
void FunctionSelection::selectCells(const QRect &selectedCells,
|
|
Shinya Kitaoka |
120a6e |
const QList<tdoubleparam *=""> &curves) {</tdoubleparam>
|
|
Shinya Kitaoka |
120a6e |
assert(selectedCells.width() == curves.size());
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < curves.size(); i++)
|
|
Shinya Kitaoka |
120a6e |
if (curves[i]) curves[i]->addRef();
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < m_selectedKeyframes.size(); i++)
|
|
Shinya Kitaoka |
120a6e |
if (m_selectedKeyframes[i].first) m_selectedKeyframes[i].first->release();
|
|
Shinya Kitaoka |
120a6e |
m_selectedKeyframes.clear();
|
|
Shinya Kitaoka |
120a6e |
double r0 = selectedCells.top();
|
|
Shinya Kitaoka |
120a6e |
double r1 = selectedCells.bottom();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Update selected keyframes
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < curves.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *curve = curves[i];
|
|
Shinya Kitaoka |
120a6e |
m_selectedKeyframes.push_back(qMakePair(curve, QSet<int>()));</int>
|
|
Shinya Kitaoka |
120a6e |
if (curve)
|
|
Shinya Kitaoka |
120a6e |
for (int j = 0; j < curve->getKeyframeCount(); j++) {
|
|
Shinya Kitaoka |
120a6e |
double f = curve->keyframeIndexToFrame(j);
|
|
Shinya Kitaoka |
120a6e |
if (r0 <= f && f <= r1) m_selectedKeyframes[i].second.insert(j);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Update selected segment
|
|
Shinya Kitaoka |
120a6e |
if (curves.size() != 1)
|
|
Shinya Kitaoka |
120a6e |
m_selectedSegment = -1;
|
|
Shinya Kitaoka |
120a6e |
else if (!curves[0]) // curves[0] may be zero
|
|
Shinya Kitaoka |
120a6e |
m_selectedSegment = -1;
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
int r0 = selectedCells.top();
|
|
Shinya Kitaoka |
120a6e |
int r1 = selectedCells.bottom();
|
|
Shinya Kitaoka |
120a6e |
int k0 = curves[0]->getPrevKeyframe(r0);
|
|
Shinya Kitaoka |
120a6e |
int k1 = curves[0]->getPrevKeyframe(r1);
|
|
Shinya Kitaoka |
120a6e |
// PrevKeyFrame does NOT include itself if the specified row is keyframe
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (k0 ==
|
|
Shinya Kitaoka |
120a6e |
curves[0]->getKeyframeCount() - 1) // select bottom of the segments
|
|
Shinya Kitaoka |
120a6e |
m_selectedSegment = -1;
|
|
Shinya Kitaoka |
120a6e |
else if (k0 != k1) // select over a keyframe
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
// then select the segment on top in the selection
|
|
Shinya Kitaoka |
120a6e |
if (curves[0]->isKeyframe(r0))
|
|
Shinya Kitaoka |
120a6e |
m_selectedSegment = k0 + 1;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
m_selectedSegment = k0;
|
|
Shinya Kitaoka |
120a6e |
} else // select single segment
|
|
Shinya Kitaoka |
120a6e |
m_selectedSegment = k0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_selectedCells = selectedCells;
|
|
Shinya Kitaoka |
120a6e |
makeCurrent();
|
|
Shinya Kitaoka |
120a6e |
emit selectionChanged();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void FunctionSelection::selectCells(const QRect &selectedCells) {
|
|
Shinya Kitaoka |
120a6e |
QList<tdoubleparam *=""> curves;</tdoubleparam>
|
|
Shinya Kitaoka |
120a6e |
for (int c = selectedCells.left(); c <= selectedCells.right(); c++)
|
|
Shinya Kitaoka |
120a6e |
curves.append(getCurveFromColumn(c));
|
|
Shinya Kitaoka |
120a6e |
selectCells(selectedCells, curves);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void FunctionSelection::select(TDoubleParam *curve, int k) {
|
|
Shinya Kitaoka |
120a6e |
int i = touchCurveIndex(curve);
|
|
Shinya Kitaoka |
120a6e |
m_selectedKeyframes[i].second.insert(k);
|
|
Shinya Kitaoka |
120a6e |
double row = curve->keyframeIndexToFrame(k);
|
|
Shinya Kitaoka |
120a6e |
if (row < (double)m_selectedCells.top()) m_selectedCells.setTop(floor(row));
|
|
Shinya Kitaoka |
120a6e |
if (row > (double)m_selectedCells.bottom())
|
|
Shinya Kitaoka |
120a6e |
m_selectedCells.setBottom(ceil(row));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_selectedSegment >= 0 // if a segment is selected
|
|
Shinya Kitaoka |
120a6e |
&& (m_selectedKeyframes.size() !=
|
|
Shinya Kitaoka |
120a6e |
1 // and there is not a single curve selected
|
|
Shinya Kitaoka |
120a6e |
|| m_selectedSegment != k ||
|
|
Shinya Kitaoka |
120a6e |
m_selectedSegment + 1 != k)) // or the new selected keyframe
|
|
Shinya Kitaoka |
120a6e |
// is not a selected segment end
|
|
Shinya Kitaoka |
120a6e |
m_selectedSegment = -1; // then clear the segment selection
|
|
Shinya Kitaoka |
120a6e |
makeCurrent();
|
|
Shinya Kitaoka |
120a6e |
emit selectionChanged();
|
|
Shinya Kitaoka |
120a6e |
m_selectedCells = QRect();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool FunctionSelection::isSelected(TDoubleParam *curve, int k) const {
|
|
Shinya Kitaoka |
120a6e |
int i = getCurveIndex(curve);
|
|
Shinya Kitaoka |
120a6e |
if (i < 0)
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
return m_selectedKeyframes[i].second.contains(k);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int FunctionSelection::getSelectedKeyframeCount() const {
|
|
Shinya Kitaoka |
120a6e |
int count = 0;
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < m_selectedKeyframes.size(); i++)
|
|
Shinya Kitaoka |
120a6e |
count += m_selectedKeyframes[i].second.size();
|
|
Shinya Kitaoka |
120a6e |
return count;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
QPair<tdoubleparam *,="" int=""> FunctionSelection::getSelectedKeyframe(</tdoubleparam>
|
|
Shinya Kitaoka |
120a6e |
int index) const {
|
|
Shinya Kitaoka |
120a6e |
if (index < 0) return QPair<tdoubleparam *,="" int="">(0, -1);</tdoubleparam>
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < m_selectedKeyframes.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
int count = m_selectedKeyframes[i].second.size();
|
|
Shinya Kitaoka |
120a6e |
if (index < count) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *curve = m_selectedKeyframes[i].first;
|
|
Shinya Kitaoka |
120a6e |
QSet<int>::const_iterator it = m_selectedKeyframes[i].second.begin();</int>
|
|
shun-iwasawa |
443318 |
std::advance(it, index);
|
|
Shinya Kitaoka |
120a6e |
return QPair<tdoubleparam *,="" int="">(curve, *it);</tdoubleparam>
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
index -= count;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return QPair<tdoubleparam *,="" int="">(0, -1);</tdoubleparam>
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// called from FunctionCurve::MousePressEvent() and
|
|
Shinya Kitaoka |
120a6e |
// NumericalColumns::SelectCells()
|
|
Shinya Kitaoka |
120a6e |
void FunctionSelection::selectSegment(TDoubleParam *curve, int k,
|
|
Shinya Kitaoka |
120a6e |
QRect selectedCells) {
|
|
Shinya Kitaoka |
120a6e |
if (curve == 0) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// if a different curve is selected the clear the old selection
|
|
Shinya Kitaoka |
120a6e |
if (m_selectedKeyframes.size() != 1 ||
|
|
Shinya Kitaoka |
120a6e |
m_selectedKeyframes[0].first != curve) {
|
|
Shinya Kitaoka |
120a6e |
curve->addRef();
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < m_selectedKeyframes.size(); i++)
|
|
Shinya Kitaoka |
120a6e |
if (m_selectedKeyframes[i].first) m_selectedKeyframes[i].first->release();
|
|
Shinya Kitaoka |
120a6e |
m_selectedKeyframes.clear();
|
|
Shinya Kitaoka |
120a6e |
m_selectedKeyframes.push_back(qMakePair(curve, QSet<int>()));</int>
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_selectedKeyframes[0].second.clear();
|
|
Shinya Kitaoka |
120a6e |
m_selectedKeyframes[0].second.insert(k); // k is keyframe id
|
|
Shinya Kitaoka |
120a6e |
m_selectedKeyframes[0].second.insert(k + 1);
|
|
Shinya Kitaoka |
120a6e |
m_selectedSegment = k;
|
|
Shinya Kitaoka |
120a6e |
m_selectedCells = selectedCells;
|
|
Shinya Kitaoka |
120a6e |
makeCurrent();
|
|
Shinya Kitaoka |
120a6e |
emit selectionChanged();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool FunctionSelection::isSegmentSelected(TDoubleParam *curve, int k) const {
|
|
Shinya Kitaoka |
120a6e |
return m_selectedKeyframes.size() == 1 &&
|
|
Shinya Kitaoka |
120a6e |
m_selectedKeyframes[0].first == curve && m_selectedSegment == k;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
QPair<tdoubleparam *,="" int=""> FunctionSelection::getSelectedSegment() const {</tdoubleparam>
|
|
Shinya Kitaoka |
120a6e |
if (m_selectedKeyframes.size() == 1 && m_selectedSegment >= 0)
|
|
Shinya Kitaoka |
120a6e |
return qMakePair(m_selectedKeyframes[0].first, m_selectedSegment);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
return qMakePair<tdoubleparam *,="" int="">(0, -1);</tdoubleparam>
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void FunctionSelection::enableCommands() {
|
|
Shinya Kitaoka |
120a6e |
enableCommand(this, "MI_Copy", &FunctionSelection::doCopy);
|
|
Shinya Kitaoka |
120a6e |
enableCommand(this, "MI_Paste", &FunctionSelection::doPaste);
|
|
Shinya Kitaoka |
120a6e |
enableCommand(this, "MI_Cut", &FunctionSelection::doCut);
|
|
Shinya Kitaoka |
120a6e |
enableCommand(this, "MI_Clear", &FunctionSelection::doDelete);
|
|
Shinya Kitaoka |
120a6e |
enableCommand(this, "MI_Insert", &FunctionSelection::insertCells);
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
enableCommand(this, "MI_ResetStep", &FunctionSelection::setStep1);
|
|
shun-iwasawa |
298c96 |
enableCommand(this, "MI_Step2", &FunctionSelection::setStep2);
|
|
shun-iwasawa |
298c96 |
enableCommand(this, "MI_Step3", &FunctionSelection::setStep3);
|
|
shun-iwasawa |
298c96 |
enableCommand(this, "MI_Step4", &FunctionSelection::setStep4);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
void FunctionSelection::doCopy() {
|
|
Shinya Kitaoka |
120a6e |
if (isEmpty()) return;
|
|
Shinya Kitaoka |
120a6e |
FunctionKeyframesData *data = new FunctionKeyframesData();
|
|
Shinya Kitaoka |
120a6e |
int columnCount = m_selectedKeyframes.size();
|
|
Shinya Kitaoka |
120a6e |
data->setColumnCount(columnCount);
|
|
Shinya Kitaoka |
120a6e |
for (int col = 0; col < columnCount; col++)
|
|
Shinya Kitaoka |
120a6e |
data->getData(col, m_selectedKeyframes[col].first, m_selectedCells.top(),
|
|
Shinya Kitaoka |
120a6e |
m_selectedKeyframes[col].second);
|
|
Shinya Kitaoka |
120a6e |
const QMimeData *oldData = QApplication::clipboard()->mimeData();
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->add(new KeyframesCopyUndo(oldData, data));
|
|
Shinya Kitaoka |
120a6e |
QApplication::clipboard()->setMimeData(data);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void FunctionSelection::doPaste() {
|
|
Shinya Kitaoka |
120a6e |
const FunctionKeyframesData *data =
|
|
Shinya Kitaoka |
120a6e |
dynamic_cast<const *="" functionkeyframesdata="">(</const>
|
|
Shinya Kitaoka |
120a6e |
QApplication::clipboard()->mimeData());
|
|
Shinya Kitaoka |
120a6e |
if (!data) return;
|
|
Shinya Kitaoka |
120a6e |
int rowCount = data->getRowCount();
|
|
Shinya Kitaoka |
120a6e |
if (rowCount <= 0) return;
|
|
Shinya Kitaoka |
120a6e |
int columnCount = data->getColumnCount();
|
|
Shinya Kitaoka |
120a6e |
double frame = 0;
|
|
Shinya Kitaoka |
120a6e |
int col = 0;
|
|
Shinya Kitaoka |
120a6e |
std::vector<tdoubleparam *=""> params;</tdoubleparam>
|
|
Shinya Kitaoka |
120a6e |
if (!m_selectedCells.isEmpty()) {
|
|
Shinya Kitaoka |
120a6e |
col = m_selectedCells.left();
|
|
Shinya Kitaoka |
120a6e |
// numeric columns
|
|
Shinya Kitaoka |
120a6e |
for (int c = 0; c < columnCount; c++) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *curve = getCurveFromColumn(col + c);
|
|
Shinya Kitaoka |
120a6e |
if (curve) params.push_back(curve);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
columnCount = (int)params.size();
|
|
Shinya Kitaoka |
120a6e |
if (columnCount <= 0) return;
|
|
Shinya Kitaoka |
120a6e |
frame = m_selectedCells.top();
|
|
Shinya Kitaoka |
120a6e |
col = m_selectedCells.left();
|
|
Shinya Kitaoka |
120a6e |
selectCells(QRect(col, frame, columnCount, rowCount));
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
// curves
|
|
Shinya Kitaoka |
120a6e |
// only single curve selection supported
|
|
Shinya Kitaoka |
120a6e |
columnCount = 1;
|
|
Shinya Kitaoka |
120a6e |
if (m_selectedKeyframes.empty()) return;
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *curve = m_selectedKeyframes[0].first;
|
|
Shinya Kitaoka |
120a6e |
if (curve == 0) return;
|
|
Shinya Kitaoka |
120a6e |
int kIndex = *(m_selectedKeyframes[0].second.begin());
|
|
Shinya Kitaoka |
120a6e |
frame = curve->keyframeIndexToFrame(kIndex);
|
|
Shinya Kitaoka |
120a6e |
params.push_back(curve);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/*--- カーブの貼り付け時に循環参照をチェックして、駄目ならアラートを返す ---*/
|
|
Shinya Kitaoka |
120a6e |
for (int c = 0; c < columnCount; c++) {
|
|
Shinya Kitaoka |
120a6e |
if (!data->isCircularReferenceFree(c, params[c])) {
|
|
Shinya Kitaoka |
120a6e |
DVGui::warning(
|
|
Shinya Kitaoka |
120a6e |
tr("There is a circular reference in the definition of the "
|
|
Shinya Kitaoka |
120a6e |
"interpolation."));
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->add(new KeyframesPasteUndo(params, data, frame));
|
|
Shinya Kitaoka |
120a6e |
for (int c = 0; c < columnCount; c++) data->setData(c, params[c], frame);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void FunctionSelection::doCut() {
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->beginBlock();
|
|
Shinya Kitaoka |
120a6e |
doCopy();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool cellsSelection = !m_selectedCells.isEmpty();
|
|
Shinya Kitaoka |
120a6e |
int bottomRow = m_selectedCells.bottom();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
KeyframesMoveUndo *moveUndo = new KeyframesMoveUndo();
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < m_selectedKeyframes.size(); i++) {
|
|
shun-iwasawa |
298c96 |
TDoubleParam *curve = m_selectedKeyframes[i].first;
|
|
shun-iwasawa |
298c96 |
QSet<int> &kk = m_selectedKeyframes[i].second;</int>
|
|
shun-iwasawa |
298c96 |
double delta = 0;
|
|
Shinya Kitaoka |
120a6e |
if (cellsSelection) delta = -m_selectedCells.height();
|
|
shun-iwasawa |
298c96 |
int n = curve ? curve->getKeyframeCount() : 0;
|
|
shun-iwasawa |
298c96 |
int j = 0;
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < n; i++) {
|
|
Shinya Kitaoka |
120a6e |
if (kk.contains(i)) {
|
|
Shinya Kitaoka |
120a6e |
if (i + 1 < n && kk.contains(i + 1) && !cellsSelection)
|
|
Shinya Kitaoka |
120a6e |
delta += curve->keyframeIndexToFrame(i) -
|
|
Shinya Kitaoka |
120a6e |
curve->keyframeIndexToFrame(i + 1);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if ((cellsSelection && bottomRow <= curve->keyframeIndexToFrame(i)) ||
|
|
Shinya Kitaoka |
120a6e |
(!cellsSelection && delta != 0))
|
|
Shinya Kitaoka |
120a6e |
moveUndo->addMovement(curve, j, delta);
|
|
Shinya Kitaoka |
120a6e |
j++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
doDelete();
|
|
Shinya Kitaoka |
120a6e |
if (moveUndo->getCount()) {
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->add(moveUndo);
|
|
Shinya Kitaoka |
120a6e |
moveUndo->redo();
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
delete moveUndo;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->endBlock();
|
|
Shinya Kitaoka |
120a6e |
selectNone();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void FunctionSelection::doDelete() {
|
|
Shinya Kitaoka |
120a6e |
if (isEmpty()) return;
|
|
Shinya Kitaoka |
120a6e |
std::vector<keyframesdeleteundo::column> columns;</keyframesdeleteundo::column>
|
|
Shinya Kitaoka |
120a6e |
for (int col = 0; col < (int)m_selectedKeyframes.size(); col++) {
|
|
Shinya Kitaoka |
120a6e |
KeyframesDeleteUndo::Column column;
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *param = m_selectedKeyframes[col].first;
|
|
Shinya Kitaoka |
120a6e |
if (!param || !param->hasKeyframes()) continue;
|
|
Shinya Kitaoka |
120a6e |
column.m_param = param;
|
|
Shinya Kitaoka |
120a6e |
column.m_keyframes = m_selectedKeyframes[col].second;
|
|
Shinya Kitaoka |
120a6e |
columns.push_back(column);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (columns.empty()) return;
|
|
Shinya Kitaoka |
120a6e |
KeyframesDeleteUndo *undo = new KeyframesDeleteUndo(columns);
|
|
Shinya Kitaoka |
120a6e |
undo->redo();
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->add(undo);
|
|
Shinya Kitaoka |
120a6e |
selectNone();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void FunctionSelection::insertCells() {
|
|
Shinya Kitaoka |
120a6e |
if (isEmpty()) return;
|
|
Shinya Kitaoka |
120a6e |
QRect selectedCells = getSelectedCells();
|
|
Shinya Kitaoka |
120a6e |
int frameDelta = selectedCells.height();
|
|
Shinya Kitaoka |
120a6e |
int row = selectedCells.top();
|
|
Shinya Kitaoka |
120a6e |
KeyframesMoveUndo *undo = new KeyframesMoveUndo();
|
|
Shinya Kitaoka |
120a6e |
for (int c = selectedCells.left(); c <= selectedCells.right(); c++) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *param = getCurveFromColumn(c);
|
|
Shinya Kitaoka |
120a6e |
if (param && param->hasKeyframes()) {
|
|
Shinya Kitaoka |
120a6e |
// Move keyframes in reverse, so their ordering remains consistent at each
|
|
Shinya Kitaoka |
120a6e |
// step
|
|
Shinya Kitaoka |
120a6e |
int k = param->getKeyframeCount() - 1;
|
|
Shinya Kitaoka |
120a6e |
for (; k >= 0 && param->keyframeIndexToFrame(k) >= row; --k)
|
|
Shinya Kitaoka |
120a6e |
undo->addMovement(param, k, frameDelta);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
undo->redo();
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->add(undo);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
shun-iwasawa |
298c96 |
void FunctionSelection::setStep(int step, bool inclusive) {
|
|
shun-iwasawa |
298c96 |
if (isEmpty()) return;
|
|
shun-iwasawa |
298c96 |
TUndoManager::manager()->beginBlock();
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
int row = getSelectedCells().top();
|
|
shun-iwasawa |
298c96 |
for (const auto &col : m_selectedKeyframes) {
|
|
shun-iwasawa |
298c96 |
TDoubleParam *curve = col.first;
|
|
shun-iwasawa |
298c96 |
// need to have at least one segment
|
|
shun-iwasawa |
298c96 |
if (!curve || curve->getKeyframeCount() <= 1) continue;
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
// consider the keyframe just before the top row of the selected cells
|
|
shun-iwasawa |
298c96 |
if (inclusive) {
|
|
shun-iwasawa |
298c96 |
int topIndex = curve->getPrevKeyframe(row);
|
|
shun-iwasawa |
298c96 |
if (topIndex != -1 && topIndex != curve->getKeyframeCount() - 1 &&
|
|
shun-iwasawa |
298c96 |
!col.second.contains(topIndex))
|
|
shun-iwasawa |
298c96 |
KeyframeSetter(curve, topIndex).setStep(step);
|
|
shun-iwasawa |
298c96 |
}
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
for (const int &kIndex : col.second) {
|
|
shun-iwasawa |
298c96 |
// ignore the last key
|
|
shun-iwasawa |
298c96 |
if (kIndex == curve->getKeyframeCount() - 1) continue;
|
|
shun-iwasawa |
298c96 |
KeyframeSetter(curve, kIndex).setStep(step);
|
|
shun-iwasawa |
298c96 |
}
|
|
shun-iwasawa |
298c96 |
}
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
TUndoManager::manager()->endBlock();
|
|
shun-iwasawa |
298c96 |
}
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
int FunctionSelection::getCommonStep(bool inclusive) {
|
|
shun-iwasawa |
298c96 |
if (isEmpty()) return -1;
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
int step = -1;
|
|
shun-iwasawa |
298c96 |
int row = getSelectedCells().top();
|
|
shun-iwasawa |
298c96 |
for (const auto &col : m_selectedKeyframes) {
|
|
shun-iwasawa |
298c96 |
TDoubleParam *curve = col.first;
|
|
shun-iwasawa |
298c96 |
// need to have at least one segment
|
|
shun-iwasawa |
298c96 |
if (!curve || curve->getKeyframeCount() <= 1) continue;
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
// consider the keyframe just before the top row of the selected cells
|
|
shun-iwasawa |
298c96 |
if (inclusive) {
|
|
shun-iwasawa |
298c96 |
int topIndex = curve->getPrevKeyframe(row);
|
|
shun-iwasawa |
298c96 |
if (topIndex != -1 && topIndex != curve->getKeyframeCount() - 1 &&
|
|
shun-iwasawa |
298c96 |
!col.second.contains(topIndex))
|
|
shun-iwasawa |
298c96 |
step = curve->getKeyframe(topIndex).m_step;
|
|
shun-iwasawa |
298c96 |
}
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
for (const int &kIndex : col.second) {
|
|
shun-iwasawa |
298c96 |
// ignore the last key
|
|
shun-iwasawa |
298c96 |
if (kIndex == curve->getKeyframeCount() - 1) continue;
|
|
shun-iwasawa |
298c96 |
int tmpStep = curve->getKeyframe(kIndex).m_step;
|
|
shun-iwasawa |
298c96 |
if (step == -1)
|
|
shun-iwasawa |
298c96 |
step = tmpStep;
|
|
shun-iwasawa |
298c96 |
else if (step != tmpStep)
|
|
shun-iwasawa |
298c96 |
return 0;
|
|
shun-iwasawa |
298c96 |
}
|
|
shun-iwasawa |
298c96 |
}
|
|
shun-iwasawa |
298c96 |
return step;
|
|
shun-iwasawa |
298c96 |
}
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
void FunctionSelection::setSegmentType(TDoubleKeyframe::Type type,
|
|
shun-iwasawa |
298c96 |
bool inclusive) {
|
|
shun-iwasawa |
298c96 |
if (isEmpty()) return;
|
|
shun-iwasawa |
298c96 |
TUndoManager::manager()->beginBlock();
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
int row = getSelectedCells().top();
|
|
shun-iwasawa |
298c96 |
for (const auto &col : m_selectedKeyframes) {
|
|
shun-iwasawa |
298c96 |
TDoubleParam *curve = col.first;
|
|
shun-iwasawa |
298c96 |
// need to have at least one segment
|
|
shun-iwasawa |
298c96 |
if (!curve || curve->getKeyframeCount() <= 1) continue;
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
// consider the keyframe just before the top row of the selected cells
|
|
shun-iwasawa |
298c96 |
if (inclusive) {
|
|
shun-iwasawa |
298c96 |
int topIndex = curve->getPrevKeyframe(row);
|
|
shun-iwasawa |
298c96 |
if (topIndex != -1 && topIndex != curve->getKeyframeCount() - 1 &&
|
|
shun-iwasawa |
298c96 |
!col.second.contains(topIndex))
|
|
shun-iwasawa |
298c96 |
KeyframeSetter(curve, topIndex).setType(type);
|
|
shun-iwasawa |
298c96 |
}
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
for (const int &kIndex : col.second) {
|
|
shun-iwasawa |
298c96 |
// ignore the last key
|
|
shun-iwasawa |
298c96 |
if (kIndex == curve->getKeyframeCount() - 1) continue;
|
|
shun-iwasawa |
298c96 |
KeyframeSetter(curve, kIndex).setType(type);
|
|
shun-iwasawa |
298c96 |
}
|
|
shun-iwasawa |
298c96 |
}
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
TUndoManager::manager()->endBlock();
|
|
shun-iwasawa |
298c96 |
}
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
int FunctionSelection::getCommonSegmentType(bool inclusive) {
|
|
shun-iwasawa |
298c96 |
if (isEmpty()) return -1;
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
int type = -1;
|
|
shun-iwasawa |
298c96 |
int row = getSelectedCells().top();
|
|
shun-iwasawa |
298c96 |
for (const auto &col : m_selectedKeyframes) {
|
|
shun-iwasawa |
298c96 |
TDoubleParam *curve = col.first;
|
|
shun-iwasawa |
298c96 |
// need to have at least one segment
|
|
shun-iwasawa |
298c96 |
if (!curve || curve->getKeyframeCount() <= 1) continue;
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
// consider the keyframe just before the top row of the selected cells
|
|
shun-iwasawa |
298c96 |
if (inclusive) {
|
|
shun-iwasawa |
298c96 |
int topIndex = curve->getPrevKeyframe(row);
|
|
shun-iwasawa |
298c96 |
if (topIndex != -1 && topIndex != curve->getKeyframeCount() - 1 &&
|
|
shun-iwasawa |
298c96 |
!col.second.contains(topIndex))
|
|
shun-iwasawa |
298c96 |
type = (int)(curve->getKeyframe(topIndex).m_type);
|
|
shun-iwasawa |
298c96 |
}
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
298c96 |
for (const int &kIndex : col.second) {
|
|
shun-iwasawa |
298c96 |
// ignore the last key
|
|
shun-iwasawa |
298c96 |
if (kIndex == curve->getKeyframeCount() - 1) continue;
|
|
shun-iwasawa |
298c96 |
int tmpType = (int)(curve->getKeyframe(kIndex).m_type);
|
|
shun-iwasawa |
298c96 |
if (type == -1)
|
|
shun-iwasawa |
298c96 |
type = tmpType;
|
|
shun-iwasawa |
298c96 |
else if (type != tmpType)
|
|
shun-iwasawa |
298c96 |
return 0;
|
|
shun-iwasawa |
298c96 |
}
|
|
shun-iwasawa |
298c96 |
}
|
|
shun-iwasawa |
298c96 |
return type;
|
|
shun-iwasawa |
298c96 |
}
|
|
shun-iwasawa |
298c96 |
|
|
shun-iwasawa |
23df06 |
QList<int> FunctionSelection::getSelectedKeyIndices(TDoubleParam *curve) {</int>
|
|
shun-iwasawa |
23df06 |
for (auto selectedParam : m_selectedKeyframes) {
|
|
shun-iwasawa |
23df06 |
if (curve == selectedParam.first) {
|
|
shun-iwasawa |
23df06 |
QList<int> ret = selectedParam.second.toList();</int>
|
|
shun-iwasawa |
23df06 |
std::sort(ret.begin(), ret.end());
|
|
shun-iwasawa |
23df06 |
return ret;
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
return QList<int>();</int>
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// FunctionKeyframesData
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
FunctionKeyframesData::FunctionKeyframesData() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
FunctionKeyframesData::~FunctionKeyframesData() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void FunctionKeyframesData::setColumnCount(int columnCount) {
|
|
Shinya Kitaoka |
120a6e |
m_keyframes.resize(columnCount);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void FunctionKeyframesData::getData(int columnIndex, TDoubleParam *curve,
|
|
Shinya Kitaoka |
120a6e |
double frame, const QSet<int> &kIndices) {</int>
|
|
Shinya Kitaoka |
120a6e |
assert(0 <= columnIndex && columnIndex < (int)m_keyframes.size());
|
|
Shinya Kitaoka |
120a6e |
Keyframes &keyframes = m_keyframes[columnIndex];
|
|
Shinya Kitaoka |
120a6e |
keyframes.clear();
|
|
Shinya Kitaoka |
120a6e |
if (!kIndices.empty()) {
|
|
Shinya Kitaoka |
120a6e |
double dFrame = -frame;
|
|
Shinya Kitaoka |
120a6e |
QSet<int>::const_iterator it;</int>
|
|
Shinya Kitaoka |
120a6e |
for (it = kIndices.begin(); it != kIndices.end(); ++it) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleKeyframe keyframe = curve->getKeyframe(*it);
|
|
Shinya Kitaoka |
120a6e |
keyframe.m_frame += dFrame;
|
|
Shinya Kitaoka |
120a6e |
keyframes.push_back(keyframe);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void FunctionKeyframesData::setData(int columnIndex, TDoubleParam *curve,
|
|
Shinya Kitaoka |
120a6e |
double frame) const {
|
|
Shinya Kitaoka |
120a6e |
assert(0 <= columnIndex && columnIndex < (int)m_keyframes.size());
|
|
Shinya Kitaoka |
120a6e |
const Keyframes &keyframes = m_keyframes[columnIndex];
|
|
Shinya Kitaoka |
120a6e |
int n = (int)keyframes.size();
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < n; i++) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleKeyframe keyframe(keyframes[i]);
|
|
Shinya Kitaoka |
120a6e |
keyframe.m_frame += frame;
|
|
Shinya Kitaoka |
120a6e |
if (i == 0 || i == n - 1) keyframe.m_linkedHandles = false;
|
|
Shinya Kitaoka |
120a6e |
curve->setKeyframe(keyframe);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
const FunctionKeyframesData::Keyframes &FunctionKeyframesData::getKeyframes(
|
|
Shinya Kitaoka |
120a6e |
int columnIndex) const {
|
|
Shinya Kitaoka |
120a6e |
assert(0 <= columnIndex && columnIndex < (int)m_keyframes.size());
|
|
Shinya Kitaoka |
120a6e |
return m_keyframes[columnIndex];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
DvMimeData *FunctionKeyframesData::clone() const {
|
|
Shinya Kitaoka |
120a6e |
FunctionKeyframesData *data = new FunctionKeyframesData();
|
|
Shinya Kitaoka |
120a6e |
data->m_keyframes = m_keyframes;
|
|
Shinya Kitaoka |
120a6e |
return data;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int FunctionKeyframesData::getRowCount() const {
|
|
Shinya Kitaoka |
120a6e |
int rowCount = 0;
|
|
Shinya Kitaoka |
120a6e |
for (int c = 0; c < (int)m_keyframes.size(); c++) {
|
|
Shinya Kitaoka |
120a6e |
const Keyframes &keyframes = m_keyframes[c];
|
|
Shinya Kitaoka |
120a6e |
if (!keyframes.empty()) {
|
|
shun-iwasawa |
298c96 |
int row = (int)(keyframes.rbegin()->m_frame);
|
|
Shinya Kitaoka |
120a6e |
if (row + 1 > rowCount) rowCount = row + 1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return rowCount;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---- カーブの貼り付け時に循環参照をチェックして、駄目ならfalseを返す ----*/
|
|
Shinya Kitaoka |
120a6e |
bool FunctionKeyframesData::isCircularReferenceFree(int columnIndex,
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *curve) const {
|
|
Shinya Kitaoka |
120a6e |
const Keyframes &keyframes = m_keyframes[columnIndex];
|
|
Shinya Kitaoka |
120a6e |
int n = (int)keyframes.size();
|
|
Shinya Kitaoka |
120a6e |
// for each key frame
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < n; i++) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleKeyframe keyframe(keyframes[i]);
|
|
Shinya Kitaoka |
120a6e |
// only check Expression type
|
|
Shinya Kitaoka |
120a6e |
if (keyframe.m_type != TDoubleKeyframe::Expression) continue;
|
|
Shinya Kitaoka |
120a6e |
// check circular reference
|
|
Shinya Kitaoka |
120a6e |
TExpression expr;
|
|
Shinya Kitaoka |
120a6e |
expr.setGrammar(curve->getGrammar());
|
|
Shinya Kitaoka |
120a6e |
expr.setText(keyframe.m_expressionText);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (dependsOn(expr, curve)) return false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|