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