|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "functionpaneltools.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// TnzQt includes
|
|
Toshihiro Shimizu |
890ddd |
#include "toonzqt/functionselection.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// TnzLib includes
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tframehandle.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// TnzCore includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tundo.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Qt includes
|
|
Toshihiro Shimizu |
890ddd |
#include <qpainter></qpainter>
|
|
Toshihiro Shimizu |
890ddd |
#include <qmouseevent></qmouseevent>
|
|
shun-iwasawa |
23df06 |
#include <qmultimap></qmultimap>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
MoveFrameDragTool::MoveFrameDragTool(FunctionPanel *panel,
|
|
Shinya Kitaoka |
120a6e |
TFrameHandle *frameHandle)
|
|
Shinya Kitaoka |
120a6e |
: m_panel(panel), m_frameHandle(frameHandle) {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void MoveFrameDragTool::drag(QMouseEvent *e) {
|
|
Shinya Kitaoka |
120a6e |
double frame = m_panel->xToFrame(e->pos().x());
|
|
Shinya Kitaoka |
120a6e |
m_panel->getSelection()->deselectAllKeyframes();
|
|
Shinya Kitaoka |
120a6e |
m_frameHandle->setFrame(frame);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
PanDragTool::PanDragTool(FunctionPanel *panel, bool xLocked, bool yLocked)
|
|
Shinya Kitaoka |
120a6e |
: m_panel(panel), m_xLocked(xLocked), m_yLocked(yLocked) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void PanDragTool::click(QMouseEvent *e) { m_oldPos = e->pos(); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void PanDragTool::drag(QMouseEvent *e) {
|
|
Shinya Kitaoka |
120a6e |
QPoint delta = e->pos() - m_oldPos;
|
|
Shinya Kitaoka |
120a6e |
if (m_xLocked) delta.setX(0);
|
|
Shinya Kitaoka |
120a6e |
if (m_yLocked) delta.setY(0);
|
|
Shinya Kitaoka |
120a6e |
m_panel->pan(delta);
|
|
Shinya Kitaoka |
120a6e |
m_oldPos = e->pos();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
/*--- Ruler部分ドラッグによるズーム ---*/
|
|
Shinya Kitaoka |
120a6e |
void ZoomDragTool::click(QMouseEvent *e) {
|
|
Shinya Kitaoka |
120a6e |
m_startPos = m_oldPos = m_startPos = e->pos();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void ZoomDragTool::drag(QMouseEvent *e) {
|
|
Shinya Kitaoka |
120a6e |
QPoint delta = e->pos() - m_oldPos;
|
|
Shinya Kitaoka |
120a6e |
m_oldPos = e->pos();
|
|
Shinya Kitaoka |
120a6e |
double sx = 1, sy = 1;
|
|
Shinya Kitaoka |
120a6e |
// reflect horizontal drag for frame zoom
|
|
Shinya Kitaoka |
120a6e |
double zoomFactor =
|
|
Shinya Kitaoka |
120a6e |
exp(-0.0075 * ((m_zoomType == FrameZoom) ? -delta.x() : delta.y()));
|
|
Shinya Kitaoka |
120a6e |
if (m_zoomType == FrameZoom)
|
|
Shinya Kitaoka |
120a6e |
sx = zoomFactor;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
sy = zoomFactor;
|
|
Shinya Kitaoka |
120a6e |
m_panel->zoom(sx, sy, m_startPos);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void ZoomDragTool::release(QMouseEvent *e) {
|
|
Shinya Kitaoka |
120a6e |
if ((e->pos() - m_startPos).manhattanLength() < 2) {
|
|
Shinya Kitaoka |
120a6e |
double frame = m_panel->xToFrame(e->pos().x());
|
|
Shinya Kitaoka |
120a6e |
if (m_panel->getFrameHandle()) m_panel->getFrameHandle()->setFrame(frame);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void RectSelectTool::click(QMouseEvent *e) {
|
|
Shinya Kitaoka |
120a6e |
m_startPos = e->pos();
|
|
Shinya Kitaoka |
120a6e |
m_rect = QRect();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void RectSelectTool::drag(QMouseEvent *e) {
|
|
Shinya Kitaoka |
120a6e |
m_rect = QRect(m_startPos, e->pos()).normalized();
|
|
Shinya Kitaoka |
120a6e |
m_panel->getSelection()->deselectAllKeyframes();
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < m_curve->getKeyframeCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
QPointF p = m_panel->getWinPos(m_curve, m_curve->getKeyframe(i));
|
|
Shinya Kitaoka |
120a6e |
if (m_rect.contains(tround(p.x()), tround(p.y())))
|
|
Shinya Kitaoka |
120a6e |
m_panel->getSelection()->select(m_curve, i);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_panel->update();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void RectSelectTool::release(QMouseEvent *e) { m_panel->update(); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void RectSelectTool::draw(QPainter &painter) {
|
|
Shinya Kitaoka |
120a6e |
painter.setPen(Qt::white);
|
|
Shinya Kitaoka |
120a6e |
painter.setBrush(QColor(255, 255, 255, 127));
|
|
Shinya Kitaoka |
120a6e |
if (!m_rect.isEmpty()) painter.drawRect(m_rect);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
MovePointDragTool::MovePointDragTool(FunctionPanel *panel, TDoubleParam *curve)
|
|
Shinya Kitaoka |
120a6e |
: m_panel(panel)
|
|
Shinya Kitaoka |
120a6e |
, m_deltaFrame(0)
|
|
Shinya Kitaoka |
120a6e |
, m_speed0Length(0)
|
|
Shinya Kitaoka |
120a6e |
, m_speed0Index(-1)
|
|
Shinya Kitaoka |
120a6e |
, m_speed1Length(0)
|
|
Shinya Kitaoka |
120a6e |
, m_speed1Index(-1)
|
|
Shinya Kitaoka |
120a6e |
, m_groupEnabled(false)
|
|
Shinya Kitaoka |
120a6e |
, m_selection(0) {
|
|
shun-iwasawa |
8f7598 |
// This undo block is closed in the destructor
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->beginBlock();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (curve) {
|
|
Shinya Kitaoka |
120a6e |
KeyframeSetter *setter = new KeyframeSetter(curve);
|
|
Shinya Kitaoka |
120a6e |
m_setters.push_back(setter);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
m_groupEnabled = true;
|
|
Shinya Kitaoka |
120a6e |
FunctionTreeModel *model = panel->getModel();
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < model->getActiveChannelCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
FunctionTreeModel::Channel *channel = model->getActiveChannel(i);
|
|
Shinya Kitaoka |
120a6e |
if (channel && channel->getParam()) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *curve = channel->getParam();
|
|
Shinya Kitaoka |
120a6e |
KeyframeSetter *setter = new KeyframeSetter(curve);
|
|
Shinya Kitaoka |
120a6e |
m_setters.push_back(setter);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
MovePointDragTool::~MovePointDragTool() {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_setters.size(); i++) delete m_setters[i];
|
|
Shinya Kitaoka |
120a6e |
m_setters.clear();
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->endBlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void MovePointDragTool::addKeyframe2(int kIndex) {
|
|
Shinya Kitaoka |
120a6e |
assert(m_setters.size() == 1);
|
|
Shinya Kitaoka |
120a6e |
if (m_setters.size() == 1) m_setters[0]->selectKeyframe(kIndex);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void MovePointDragTool::createKeyframe(double frame) {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_setters.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
KeyframeSetter *setter = m_setters[i];
|
|
Shinya Kitaoka |
120a6e |
int kIndex = setter->createKeyframe(tround(frame));
|
|
Shinya Kitaoka |
120a6e |
setter->selectKeyframe(kIndex);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void MovePointDragTool::selectKeyframes(double frame) {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_setters.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
KeyframeSetter *setter = m_setters[i];
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *curve = setter->getCurve();
|
|
Shinya Kitaoka |
120a6e |
setter->setPixelRatio(m_panel->getPixelRatio(curve));
|
|
Shinya Kitaoka |
120a6e |
int kIndex = curve->getClosestKeyframe(frame);
|
|
Shinya Kitaoka |
120a6e |
if (kIndex >= 0) {
|
|
Shinya Kitaoka |
120a6e |
double kf = curve->keyframeIndexToFrame(kIndex);
|
|
Shinya Kitaoka |
120a6e |
if (fabs(kf - frame) < 0.01) setter->selectKeyframe(kIndex);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void MovePointDragTool::setSelection(FunctionSelection *selection) {
|
|
Shinya Kitaoka |
120a6e |
if (selection) {
|
|
Shinya Kitaoka |
120a6e |
assert(m_setters.size() == 1);
|
|
Shinya Kitaoka |
120a6e |
if (m_setters.size() == 1) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *curve = m_setters[0]->getCurve();
|
|
Shinya Kitaoka |
120a6e |
assert(curve);
|
|
Shinya Kitaoka |
120a6e |
if (curve) {
|
|
Shinya Kitaoka |
120a6e |
m_selection = selection;
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < curve->getKeyframeCount(); i++)
|
|
Shinya Kitaoka |
120a6e |
if (selection->isSelected(curve, i)) addKeyframe2(i);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
m_selection = selection;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void MovePointDragTool::click(QMouseEvent *e) {
|
|
Shinya Kitaoka |
120a6e |
m_startPos = m_oldPos = e->pos();
|
|
Shinya Kitaoka |
120a6e |
m_deltaFrame = 0;
|
|
Shinya Kitaoka |
120a6e |
double frame = m_panel->xToFrame(e->pos().x());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_setters.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
KeyframeSetter *setter = m_setters[i];
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *curve = setter->getCurve();
|
|
Shinya Kitaoka |
120a6e |
setter->setPixelRatio(m_panel->getPixelRatio(curve));
|
|
Shinya Kitaoka |
120a6e |
if (!m_groupEnabled) {
|
|
Shinya Kitaoka |
120a6e |
int kIndex = curve->getClosestKeyframe(frame);
|
|
Shinya Kitaoka |
120a6e |
if (kIndex >= 0) {
|
|
Shinya Kitaoka |
120a6e |
double kf = curve->keyframeIndexToFrame(kIndex);
|
|
Shinya Kitaoka |
120a6e |
if (fabs(kf - frame) < 1) setter->selectKeyframe(kIndex);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void MovePointDragTool::drag(QMouseEvent *e) {
|
|
Shinya Kitaoka |
120a6e |
QPoint pos = e->pos();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// if shift is pressed then apply constraints (only horizontal or vertical
|
|
Shinya Kitaoka |
120a6e |
// moves)
|
|
Shinya Kitaoka |
120a6e |
if (e->modifiers() & Qt::ShiftModifier) {
|
|
Shinya Kitaoka |
120a6e |
QPoint delta = e->pos() - m_startPos;
|
|
Shinya Kitaoka |
120a6e |
if (abs(delta.x()) > abs(delta.y()))
|
|
Shinya Kitaoka |
120a6e |
pos.setY(m_startPos.y());
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
pos.setX(m_startPos.x());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_groupEnabled) pos.setY(m_startPos.y());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
QPoint oldPos = m_oldPos;
|
|
Shinya Kitaoka |
120a6e |
m_oldPos = pos;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// compute frame increment. it must be an integer
|
|
Shinya Kitaoka |
120a6e |
double totalDFrame =
|
|
Shinya Kitaoka |
120a6e |
tround(m_panel->xToFrame(pos.x()) - m_panel->xToFrame(m_startPos.x()));
|
|
Shinya Kitaoka |
120a6e |
double dFrame = totalDFrame - m_deltaFrame;
|
|
Shinya Kitaoka |
120a6e |
m_deltaFrame = totalDFrame;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_setters.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
KeyframeSetter *setter = m_setters[i];
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *curve = setter->getCurve();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// compute value increment
|
|
Shinya Kitaoka |
120a6e |
double dValue = m_panel->yToValue(curve, pos.y()) -
|
|
Shinya Kitaoka |
120a6e |
m_panel->yToValue(curve, oldPos.y());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
setter->moveKeyframes(dFrame, dValue);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (m_selection != 0 && m_setters.size() == 1) {
|
|
Shinya Kitaoka |
120a6e |
KeyframeSetter *setter = m_setters[0];
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_selection->deselectAllKeyframes();
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < setter->getCurve()->getKeyframeCount(); i++)
|
|
Shinya Kitaoka |
120a6e |
if (setter->isSelected(i)) m_selection->select(setter->getCurve(), i);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_panel->update();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void MovePointDragTool::release(QMouseEvent *e) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
MoveHandleDragTool::MoveHandleDragTool(FunctionPanel *panel,
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *curve, int kIndex,
|
|
Shinya Kitaoka |
120a6e |
Handle handle)
|
|
Shinya Kitaoka |
120a6e |
: m_panel(panel)
|
|
Shinya Kitaoka |
120a6e |
, m_curve(curve)
|
|
Shinya Kitaoka |
120a6e |
, m_kIndex(kIndex)
|
|
Shinya Kitaoka |
120a6e |
, m_handle(handle)
|
|
Shinya Kitaoka |
120a6e |
, m_deltaFrame(0)
|
|
Shinya Kitaoka |
120a6e |
, m_setter(curve, kIndex)
|
|
Shinya Kitaoka |
120a6e |
, m_segmentWidth(0)
|
|
Shinya Kitaoka |
120a6e |
, m_channelGroup(0) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void MoveHandleDragTool::click(QMouseEvent *e) {
|
|
Shinya Kitaoka |
120a6e |
m_startPos = e->pos();
|
|
Shinya Kitaoka |
120a6e |
// m_startPos = m_oldPos = e->pos();
|
|
Shinya Kitaoka |
120a6e |
m_deltaFrame = 0;
|
|
Shinya Kitaoka |
120a6e |
m_keyframe = m_curve->getKeyframe(m_kIndex);
|
|
Shinya Kitaoka |
120a6e |
m_keyframe.m_value = m_curve->getValue(m_keyframe.m_frame);
|
|
Shinya Kitaoka |
120a6e |
if (m_handle == FunctionPanel::SpeedIn)
|
|
Shinya Kitaoka |
120a6e |
m_keyframe.m_value = m_curve->getValue(m_keyframe.m_frame, true);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_channelGroup) {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < m_channelGroup->getChildCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
TreeModel::Item *child = m_channelGroup->getChild(i);
|
|
Shinya Kitaoka |
120a6e |
FunctionTreeModel::Channel *channel =
|
|
Shinya Kitaoka |
120a6e |
dynamic_cast<functiontreemodel::channel *="">(child);</functiontreemodel::channel>
|
|
Shinya Kitaoka |
120a6e |
if (channel && m_curve != channel->getParam()) {
|
|
Shinya Kitaoka |
120a6e |
if (channel->getParam()->isKeyframe(m_keyframe.m_frame)) {
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_handle == FunctionPanel::EaseInPercentage && m_kIndex > 0) {
|
|
Shinya Kitaoka |
120a6e |
double previousFrame = m_curve->keyframeIndexToFrame(m_kIndex - 1);
|
|
Shinya Kitaoka |
120a6e |
m_segmentWidth = m_keyframe.m_frame - previousFrame;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (m_handle == FunctionPanel::EaseOutPercentage &&
|
|
Shinya Kitaoka |
120a6e |
m_kIndex + 1 < m_curve->getKeyframeCount()) {
|
|
Shinya Kitaoka |
120a6e |
double nextFrame = m_curve->keyframeIndexToFrame(m_kIndex + 1);
|
|
Shinya Kitaoka |
120a6e |
m_segmentWidth = nextFrame - m_keyframe.m_frame;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
TPointD speed;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_keyframe.m_linkedHandles) {
|
|
Shinya Kitaoka |
120a6e |
if (m_handle == FunctionPanel::SpeedIn &&
|
|
Shinya Kitaoka |
120a6e |
m_kIndex + 1 < m_curve->getKeyframeCount() &&
|
|
Shinya Kitaoka |
120a6e |
(m_keyframe.m_type != TDoubleKeyframe::SpeedInOut &&
|
|
Shinya Kitaoka |
120a6e |
(m_keyframe.m_type != TDoubleKeyframe::Expression ||
|
|
Shinya Kitaoka |
120a6e |
m_keyframe.m_expressionText.find("cycle") == std::string::npos)))
|
|
Shinya Kitaoka |
120a6e |
speed = m_curve->getSpeedIn(m_kIndex);
|
|
Shinya Kitaoka |
120a6e |
else if (m_handle == FunctionPanel::SpeedOut &&
|
|
Shinya Kitaoka |
120a6e |
m_keyframe.m_prevType != TDoubleKeyframe::SpeedInOut &&
|
|
Shinya Kitaoka |
120a6e |
m_kIndex > 0)
|
|
Shinya Kitaoka |
120a6e |
speed = m_curve->getSpeedOut(m_kIndex);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (norm2(speed) > 0.001) {
|
|
Shinya Kitaoka |
120a6e |
QPointF a = m_panel->getWinPos(m_curve, speed) -
|
|
Shinya Kitaoka |
120a6e |
m_panel->getWinPos(m_curve, TPointD());
|
|
Shinya Kitaoka |
120a6e |
double aa = 1.0 / sqrt(a.x() * a.x() + a.y() * a.y());
|
|
Shinya Kitaoka |
120a6e |
m_nSpeed = QPointF(-a.y() * aa, a.x() * aa);
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
m_nSpeed = QPointF();
|
|
Shinya Kitaoka |
120a6e |
m_setter.setPixelRatio(m_panel->getPixelRatio(m_curve));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void MoveHandleDragTool::drag(QMouseEvent *e) {
|
|
Shinya Kitaoka |
120a6e |
if (!m_curve) return;
|
|
Shinya Kitaoka |
120a6e |
QPoint pos = e->pos();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// if shift is pressed then apply constraints (only horizontal or vertical
|
|
Shinya Kitaoka |
120a6e |
// moves)
|
|
Shinya Kitaoka |
120a6e |
if (e->modifiers() & Qt::ShiftModifier) {
|
|
Shinya Kitaoka |
120a6e |
QPoint delta = e->pos() - m_startPos;
|
|
Shinya Kitaoka |
120a6e |
if (abs(delta.x()) > abs(delta.y()))
|
|
Shinya Kitaoka |
120a6e |
pos.setY(m_startPos.y());
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
pos.setX(m_startPos.x());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// QPoint oldPos = m_oldPos;
|
|
Shinya Kitaoka |
120a6e |
// m_oldPos = pos;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
QPointF p0 = m_panel->getWinPos(m_curve, m_keyframe);
|
|
Shinya Kitaoka |
120a6e |
QPointF posF(pos);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_nSpeed != QPointF(0, 0)) {
|
|
Shinya Kitaoka |
120a6e |
QPointF delta = posF - p0;
|
|
Shinya Kitaoka |
120a6e |
posF -= m_nSpeed * (delta.x() * m_nSpeed.x() + delta.y() * m_nSpeed.y());
|
|
Shinya Kitaoka |
120a6e |
if ((m_handle == FunctionPanel::SpeedIn && posF.x() > p0.x()) ||
|
|
Shinya Kitaoka |
120a6e |
(m_handle == FunctionPanel::SpeedOut && posF.x() < p0.x()))
|
|
Shinya Kitaoka |
120a6e |
posF = p0;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if ((m_handle == FunctionPanel::SpeedIn && posF.x() > p0.x()) ||
|
|
Shinya Kitaoka |
120a6e |
(m_handle == FunctionPanel::SpeedOut && posF.x() < p0.x()))
|
|
Shinya Kitaoka |
120a6e |
posF.setX(p0.x());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double frame = m_panel->xToFrame(posF.x());
|
|
Shinya Kitaoka |
120a6e |
double value = m_panel->yToValue(m_curve, posF.y());
|
|
Shinya Kitaoka |
120a6e |
TPointD handlePos(frame - m_keyframe.m_frame, value - m_keyframe.m_value);
|
|
Shinya Kitaoka |
120a6e |
switch (m_handle) {
|
|
Shinya Kitaoka |
120a6e |
case FunctionPanel::SpeedIn:
|
|
Shinya Kitaoka |
120a6e |
if (m_keyframe.m_type != TDoubleKeyframe::SpeedInOut) {
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_setter.setSpeedIn(handlePos);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case FunctionPanel::SpeedOut:
|
|
Shinya Kitaoka |
120a6e |
m_setter.setSpeedOut(handlePos);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case FunctionPanel::EaseIn:
|
|
Shinya Kitaoka |
120a6e |
m_setter.setEaseIn(handlePos.x);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case FunctionPanel::EaseOut:
|
|
Shinya Kitaoka |
120a6e |
m_setter.setEaseOut(handlePos.x);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case FunctionPanel::EaseInPercentage:
|
|
Shinya Kitaoka |
120a6e |
if (m_segmentWidth > 0)
|
|
Shinya Kitaoka |
120a6e |
m_setter.setEaseIn(100.0 * handlePos.x / m_segmentWidth);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case FunctionPanel::EaseOutPercentage:
|
|
Shinya Kitaoka |
120a6e |
if (m_segmentWidth > 0)
|
|
Shinya Kitaoka |
120a6e |
m_setter.setEaseOut(100.0 * handlePos.x / m_segmentWidth);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case 100:
|
|
Shinya Kitaoka |
120a6e |
case 101:
|
|
Shinya Kitaoka |
120a6e |
case 102:
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
default:
|
|
Shinya Kitaoka |
120a6e |
assert(0);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_panel->update();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void MoveHandleDragTool::release(QMouseEvent *e) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
MoveGroupHandleDragTool::MoveGroupHandleDragTool(FunctionPanel *panel,
|
|
Shinya Kitaoka |
120a6e |
double keyframePosition,
|
|
Shinya Kitaoka |
120a6e |
Handle handle)
|
|
Shinya Kitaoka |
120a6e |
: m_panel(panel), m_keyframePosition(keyframePosition), m_handle(handle) {
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->beginBlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
MoveGroupHandleDragTool::~MoveGroupHandleDragTool() {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_setters.size(); i++) delete m_setters[i].second;
|
|
Shinya Kitaoka |
120a6e |
m_setters.clear();
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->endBlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void MoveGroupHandleDragTool::click(QMouseEvent *e) {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_setters.size(); i++) delete m_setters[i].second;
|
|
Shinya Kitaoka |
120a6e |
m_setters.clear();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
FunctionTreeModel *model = m_panel->getModel();
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < model->getActiveChannelCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
FunctionTreeModel::Channel *channel = model->getActiveChannel(i);
|
|
Shinya Kitaoka |
120a6e |
if (channel && channel->getParam()) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleParam *curve = channel->getParam();
|
|
Shinya Kitaoka |
120a6e |
int kIndex = curve->getClosestKeyframe(m_keyframePosition);
|
|
Shinya Kitaoka |
120a6e |
KeyframeSetter *setter = new KeyframeSetter(curve, kIndex);
|
|
Shinya Kitaoka |
120a6e |
setter->setPixelRatio(m_panel->getPixelRatio(curve));
|
|
Shinya Kitaoka |
120a6e |
TDoubleKeyframe kf = curve->getKeyframe(kIndex);
|
|
Shinya Kitaoka |
120a6e |
m_setters.push_back(std::make_pair(kf, setter));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void MoveGroupHandleDragTool::drag(QMouseEvent *e) {
|
|
Shinya Kitaoka |
120a6e |
// if(!m_curve) return;
|
|
Shinya Kitaoka |
120a6e |
QPoint pos = e->pos();
|
|
Shinya Kitaoka |
120a6e |
QPointF posF(pos);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
if(m_nSpeed != QPointF(0,0))
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Shinya Kitaoka |
120a6e |
QPointF delta = posF-p0;
|
|
Shinya Kitaoka |
120a6e |
posF -= m_nSpeed*(delta.x()*m_nSpeed.x()+delta.y()*m_nSpeed.y());
|
|
Shinya Kitaoka |
120a6e |
if( m_handle == FunctionPanel::SpeedIn && posF.x()>p0.x()
|
|
Shinya Kitaoka |
120a6e |
|| m_handle == FunctionPanel::SpeedOut && posF.x()
|
|
Shinya Kitaoka |
120a6e |
posF = p0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
if( m_handle == FunctionPanel::SpeedIn && posF.x()>p0.x()
|
|
Shinya Kitaoka |
120a6e |
|| m_handle == FunctionPanel::SpeedOut && posF.x()
|
|
Shinya Kitaoka |
120a6e |
posF.setX(p0.x());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
double frame = m_panel->xToFrame(posF.x());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_setters.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleKeyframe kf = m_setters[i].first;
|
|
Shinya Kitaoka |
120a6e |
KeyframeSetter *setter = m_setters[i].second;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (m_handle == 101) // why the magic numbers... use enums!
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Shinya Kitaoka |
120a6e |
kf.m_speedOut.x = frame - kf.m_frame;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
switch (kf.m_type) {
|
|
Shinya Kitaoka |
120a6e |
case TDoubleKeyframe::SpeedInOut:
|
|
Shinya Kitaoka |
120a6e |
setter->setSpeedOut(kf.m_speedOut);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TDoubleKeyframe::EaseInOut:
|
|
Shinya Kitaoka |
120a6e |
setter->setEaseOut(kf.m_speedOut.x);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
default:
|
|
Shinya Kitaoka |
120a6e |
assert(false);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else if (m_handle == 102) // aagghhrrr
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
kf.m_speedIn.x = frame - kf.m_frame;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
switch (kf.m_prevType) {
|
|
Shinya Kitaoka |
120a6e |
case TDoubleKeyframe::SpeedInOut:
|
|
Shinya Kitaoka |
120a6e |
setter->setSpeedIn(kf.m_speedIn);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TDoubleKeyframe::EaseInOut:
|
|
Shinya Kitaoka |
120a6e |
setter->setEaseIn(kf.m_speedIn.x);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
default:
|
|
Shinya Kitaoka |
120a6e |
assert(false);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
switch(m_handle)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
case FunctionPanel::SpeedIn:
|
|
Shinya Kitaoka |
120a6e |
if(m_keyframe.m_type != TDoubleKeyframe::SpeedInOut)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_setter.setSpeedIn(handlePos);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case FunctionPanel::SpeedOut:m_setter.setSpeedOut(handlePos); break;
|
|
Shinya Kitaoka |
120a6e |
case FunctionPanel::EaseIn:m_setter.setEaseIn(handlePos.x); break;
|
|
Shinya Kitaoka |
120a6e |
case FunctionPanel::EaseOut:m_setter.setEaseOut(handlePos.x); break;
|
|
Shinya Kitaoka |
120a6e |
case FunctionPanel::EaseInPercentage:
|
|
Shinya Kitaoka |
120a6e |
if(m_segmentWidth>0)
|
|
Shinya Kitaoka |
120a6e |
m_setter.setEaseIn(100.0*handlePos.x/m_segmentWidth);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case FunctionPanel::EaseOutPercentage:
|
|
Shinya Kitaoka |
120a6e |
if(m_segmentWidth>0)
|
|
Shinya Kitaoka |
120a6e |
m_setter.setEaseOut(100.0*handlePos.x/m_segmentWidth);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case 100:
|
|
Shinya Kitaoka |
120a6e |
case 101:
|
|
Shinya Kitaoka |
120a6e |
case 102:
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
default:assert(0);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Shinya Kitaoka |
120a6e |
m_panel->update();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void MoveGroupHandleDragTool::release(QMouseEvent *e) {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_setters.size(); i++) delete m_setters[i].second;
|
|
Shinya Kitaoka |
120a6e |
m_setters.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
//=============================================================================
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
StretchPointDragTool::StretchPointDragTool(FunctionPanel *panel,
|
|
shun-iwasawa |
23df06 |
TDoubleParam *curve, int leftId,
|
|
shun-iwasawa |
23df06 |
int rightId, bool moveLeft)
|
|
shun-iwasawa |
23df06 |
: m_panel(panel), m_curve(curve), m_moveLeft(moveLeft) {
|
|
shun-iwasawa |
23df06 |
// This undo block is closed in the destructor
|
|
shun-iwasawa |
23df06 |
TUndoManager::manager()->beginBlock();
|
|
shun-iwasawa |
23df06 |
for (int k = leftId; k <= rightId; k++) {
|
|
shun-iwasawa |
23df06 |
KeyframeSetter *setter = new KeyframeSetter(curve);
|
|
shun-iwasawa |
23df06 |
setter->selectKeyframe(k);
|
|
shun-iwasawa |
23df06 |
m_keys.append({k, curve->getKeyframe(k).m_frame,
|
|
shun-iwasawa |
23df06 |
curve->getKeyframe(k).m_speedIn,
|
|
shun-iwasawa |
23df06 |
curve->getKeyframe(k).m_speedOut, setter});
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
m_previousRange =
|
|
shun-iwasawa |
23df06 |
m_keys.value(rightId).orgFramePos - m_keys.value(leftId).orgFramePos;
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
StretchPointDragTool::~StretchPointDragTool() {
|
|
shun-iwasawa |
23df06 |
TUndoManager::manager()->endBlock();
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
void StretchPointDragTool::click(QMouseEvent *e) {
|
|
shun-iwasawa |
23df06 |
m_clickedFrame = m_panel->xToFrame(e->pos().x());
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
void StretchPointDragTool::drag(QMouseEvent *e) {
|
|
shun-iwasawa |
23df06 |
double currentPosFrame = m_panel->xToFrame(e->pos().x());
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
// moved distance
|
|
shun-iwasawa |
23df06 |
double dFrame = currentPosFrame - m_clickedFrame;
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
double orgRange = m_keys.last().orgFramePos - m_keys.first().orgFramePos;
|
|
shun-iwasawa |
23df06 |
// frame range after stretched
|
|
shun-iwasawa |
23df06 |
double stretchedRange = (m_moveLeft) ? orgRange - dFrame : orgRange + dFrame;
|
|
shun-iwasawa |
23df06 |
// the frame range should not be smaller than [selected key amount] - 1.
|
|
shun-iwasawa |
23df06 |
stretchedRange = std::max(stretchedRange, (double)m_keys.size() - 1.);
|
|
shun-iwasawa |
23df06 |
// selection should not extend the neighbor unselected key
|
|
shun-iwasawa |
23df06 |
if (m_moveLeft && m_keys.first().kIndex > 0) {
|
|
shun-iwasawa |
23df06 |
double maxRange = m_keys.last().orgFramePos -
|
|
shun-iwasawa |
23df06 |
m_curve->getKeyframe(m_keys.first().kIndex - 1).m_frame -
|
|
shun-iwasawa |
23df06 |
1.;
|
|
shun-iwasawa |
23df06 |
stretchedRange = std::min(stretchedRange, maxRange);
|
|
shun-iwasawa |
23df06 |
} else if (!m_moveLeft &&
|
|
shun-iwasawa |
23df06 |
m_keys.last().kIndex < m_curve->getKeyframeCount() - 1) {
|
|
shun-iwasawa |
23df06 |
double maxRange = m_curve->getKeyframe(m_keys.last().kIndex + 1).m_frame -
|
|
shun-iwasawa |
23df06 |
m_keys.first().orgFramePos - 1.;
|
|
shun-iwasawa |
23df06 |
stretchedRange = std::min(stretchedRange, maxRange);
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
if (stretchedRange == m_previousRange) return;
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
// compute the key frame positions (int) after stretching
|
|
shun-iwasawa |
23df06 |
QMultiMap<int, int=""> keyPlacement; // frame(int) - kIndex multimap</int,>
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
// if the frame range is equal to [selected key amount] - 1, keys will be
|
|
shun-iwasawa |
23df06 |
// "packed" in every frames.
|
|
shun-iwasawa |
23df06 |
if ((int)std::round(stretchedRange) == m_keys.size() - 1) {
|
|
shun-iwasawa |
23df06 |
int f = (m_moveLeft) ? (int)(m_keys.last().orgFramePos - stretchedRange)
|
|
shun-iwasawa |
23df06 |
: (int)m_keys.first().orgFramePos;
|
|
shun-iwasawa |
23df06 |
for (auto keyInfo : m_keys) {
|
|
shun-iwasawa |
23df06 |
keyPlacement.insert(f, keyInfo.kIndex);
|
|
shun-iwasawa |
23df06 |
f++;
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
} else { // other cases
|
|
shun-iwasawa |
23df06 |
// stretch ratio
|
|
shun-iwasawa |
23df06 |
double stretchRatio = stretchedRange / orgRange;
|
|
shun-iwasawa |
23df06 |
double pivot =
|
|
shun-iwasawa |
23df06 |
(m_moveLeft) ? m_keys.last().orgFramePos : m_keys.first().orgFramePos;
|
|
shun-iwasawa |
23df06 |
// compute preferable key frame positions (double) after stretching
|
|
shun-iwasawa |
23df06 |
QMap<int, double=""> stretchedKeyPlacement; // kIndex - frame(double)</int,>
|
|
shun-iwasawa |
23df06 |
for (auto keyInfo : m_keys) {
|
|
shun-iwasawa |
23df06 |
double sf =
|
|
shun-iwasawa |
23df06 |
pivot * (1. - stretchRatio) + keyInfo.orgFramePos * stretchRatio;
|
|
shun-iwasawa |
23df06 |
stretchedKeyPlacement.insert(keyInfo.kIndex, sf);
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
// now, put keys in integer frame positions, minimizing error.
|
|
shun-iwasawa |
23df06 |
// first, put the keys at both ends
|
|
shun-iwasawa |
23df06 |
int kFrom = m_keys.first().kIndex;
|
|
shun-iwasawa |
23df06 |
int kTo = m_keys.last().kIndex;
|
|
shun-iwasawa |
23df06 |
keyPlacement.insert((int)std::round(stretchedKeyPlacement.value(kFrom)),
|
|
shun-iwasawa |
23df06 |
kFrom);
|
|
shun-iwasawa |
23df06 |
keyPlacement.insert((int)std::round(stretchedKeyPlacement.value(kTo)), kTo);
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
for (int i = 1; i < m_keys.size() - 1;
|
|
shun-iwasawa |
23df06 |
i++) { // put other intermediate keys
|
|
shun-iwasawa |
23df06 |
keyInfo info = m_keys.at(i);
|
|
shun-iwasawa |
23df06 |
// if the nearest integer position is vacant, put the key and continue
|
|
shun-iwasawa |
23df06 |
int tmp_f = (int)std::round(stretchedKeyPlacement.value(info.kIndex));
|
|
shun-iwasawa |
23df06 |
if (!keyPlacement.contains(tmp_f)) {
|
|
shun-iwasawa |
23df06 |
keyPlacement.insert(tmp_f, info.kIndex);
|
|
shun-iwasawa |
23df06 |
continue;
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
// evaluate errors with two candidate - insert key at round down or round
|
|
shun-iwasawa |
23df06 |
// up postions. inserting the key may push out the existing key.
|
|
shun-iwasawa |
23df06 |
int f1 = (int)std::floor(stretchedKeyPlacement.value(info.kIndex));
|
|
shun-iwasawa |
23df06 |
int f2 = f1 + 1;
|
|
shun-iwasawa |
23df06 |
{
|
|
shun-iwasawa |
23df06 |
bool ok1 = true;
|
|
shun-iwasawa |
23df06 |
bool ok2 = true;
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
// a list after inserting the key at round down position
|
|
shun-iwasawa |
23df06 |
QMultiMap<int, int=""> candidate1 =</int,>
|
|
shun-iwasawa |
23df06 |
keyPlacement; // frame(int) - kIndex multimap
|
|
shun-iwasawa |
23df06 |
int moveId = candidate1.value(f1);
|
|
shun-iwasawa |
23df06 |
candidate1.insert(f1, info.kIndex);
|
|
shun-iwasawa |
23df06 |
while (1) {
|
|
shun-iwasawa |
23df06 |
// move the key to the previous frame
|
|
shun-iwasawa |
23df06 |
candidate1.remove(f1, moveId);
|
|
shun-iwasawa |
23df06 |
// if the frame is vacant, put the key and break
|
|
shun-iwasawa |
23df06 |
if (!candidate1.contains(f1 - 1)) {
|
|
shun-iwasawa |
23df06 |
candidate1.insert(f1 - 1, moveId);
|
|
shun-iwasawa |
23df06 |
break;
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
// if the frame is occupied, switch the current moving key and "push
|
|
shun-iwasawa |
23df06 |
// out" it
|
|
shun-iwasawa |
23df06 |
int occupiedId = candidate1.value(f1 - 1);
|
|
shun-iwasawa |
23df06 |
candidate1.insert(f1 - 1, moveId);
|
|
shun-iwasawa |
23df06 |
moveId = occupiedId;
|
|
shun-iwasawa |
23df06 |
f1 -= 1;
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
// the moving key should not be the first one
|
|
shun-iwasawa |
23df06 |
if (moveId == kFrom) {
|
|
shun-iwasawa |
23df06 |
ok1 = false;
|
|
shun-iwasawa |
23df06 |
break;
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
// a list after inserting the key at round up position
|
|
shun-iwasawa |
23df06 |
QMultiMap<int, int=""> candidate2 =</int,>
|
|
shun-iwasawa |
23df06 |
keyPlacement; // frame(int) - kIndex multimap
|
|
shun-iwasawa |
23df06 |
moveId = candidate2.value(f2);
|
|
shun-iwasawa |
23df06 |
candidate2.insert(f2, info.kIndex);
|
|
shun-iwasawa |
23df06 |
while (1) {
|
|
shun-iwasawa |
23df06 |
// move the key to the nexy frame
|
|
shun-iwasawa |
23df06 |
candidate2.remove(f2, moveId);
|
|
shun-iwasawa |
23df06 |
// if the frame is vacant, put the key and break
|
|
shun-iwasawa |
23df06 |
if (!candidate2.contains(f2 + 1)) {
|
|
shun-iwasawa |
23df06 |
candidate2.insert(f2 + 1, moveId);
|
|
shun-iwasawa |
23df06 |
break;
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
// if the frame is occupied, switch the current moving key and "push
|
|
shun-iwasawa |
23df06 |
// out" it
|
|
shun-iwasawa |
23df06 |
int occupiedId = candidate2.value(f2 + 1);
|
|
shun-iwasawa |
23df06 |
candidate2.insert(f2 + 1, moveId);
|
|
shun-iwasawa |
23df06 |
moveId = occupiedId;
|
|
shun-iwasawa |
23df06 |
f2 += 1;
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
// the moving key should not be the last one
|
|
shun-iwasawa |
23df06 |
if (moveId == kTo) {
|
|
shun-iwasawa |
23df06 |
ok2 = false;
|
|
shun-iwasawa |
23df06 |
break;
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
if (!ok2)
|
|
shun-iwasawa |
23df06 |
keyPlacement = candidate1;
|
|
shun-iwasawa |
23df06 |
else if (!ok1)
|
|
shun-iwasawa |
23df06 |
keyPlacement = candidate2;
|
|
shun-iwasawa |
23df06 |
else {
|
|
shun-iwasawa |
23df06 |
double error1 = 0.;
|
|
shun-iwasawa |
23df06 |
QMultiMap<int, int="">::const_iterator i = candidate1.constBegin();</int,>
|
|
shun-iwasawa |
23df06 |
while (i != candidate1.constEnd()) {
|
|
shun-iwasawa |
23df06 |
error1 += std::abs((double)i.key() -
|
|
shun-iwasawa |
23df06 |
stretchedKeyPlacement.value(i.value()));
|
|
shun-iwasawa |
23df06 |
++i;
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
double error2 = 0.;
|
|
shun-iwasawa |
23df06 |
i = candidate2.constBegin();
|
|
shun-iwasawa |
23df06 |
while (i != candidate2.constEnd()) {
|
|
shun-iwasawa |
23df06 |
error2 += std::abs((double)i.key() -
|
|
shun-iwasawa |
23df06 |
stretchedKeyPlacement.value(i.value()));
|
|
shun-iwasawa |
23df06 |
++i;
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
if (error1 <= error2)
|
|
shun-iwasawa |
23df06 |
keyPlacement = candidate1;
|
|
shun-iwasawa |
23df06 |
else
|
|
shun-iwasawa |
23df06 |
keyPlacement = candidate2;
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
// each setter will move key frame
|
|
shun-iwasawa |
23df06 |
bool extending = stretchedRange > m_previousRange;
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
QList<double> segRatio;</double>
|
|
shun-iwasawa |
23df06 |
for (int i = 0; i < m_keys.size() - 1; i++) {
|
|
shun-iwasawa |
23df06 |
double orgSegLength =
|
|
shun-iwasawa |
23df06 |
m_keys.at(i + 1).orgFramePos - m_keys.at(i).orgFramePos;
|
|
shun-iwasawa |
23df06 |
double newSegLength = (double)(keyPlacement.key(m_keys.at(i + 1).kIndex) -
|
|
shun-iwasawa |
23df06 |
keyPlacement.key(m_keys.at(i).kIndex));
|
|
shun-iwasawa |
23df06 |
segRatio.append(newSegLength / orgSegLength);
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
// dragging left + shrink or dragging right + extend cases
|
|
shun-iwasawa |
23df06 |
// move from right key to left key
|
|
shun-iwasawa |
23df06 |
int start = (m_moveLeft != extending) ? m_keys.size() - 1 : 0;
|
|
shun-iwasawa |
23df06 |
int end = (m_moveLeft != extending) ? -1 : m_keys.size();
|
|
shun-iwasawa |
23df06 |
int dki = (m_moveLeft != extending) ? -1 : 1;
|
|
shun-iwasawa |
23df06 |
for (int ki = start; ki != end; ki += dki) {
|
|
shun-iwasawa |
23df06 |
int kId = m_keys[ki].kIndex;
|
|
shun-iwasawa |
23df06 |
int curFrame = (int)std::round(m_curve->getKeyframe(kId).m_frame);
|
|
shun-iwasawa |
23df06 |
int dstFrame = keyPlacement.key(kId);
|
|
shun-iwasawa |
23df06 |
if (curFrame != dstFrame) {
|
|
shun-iwasawa |
23df06 |
m_keys[ki].setter->moveKeyframes(dstFrame - curFrame, 0.);
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
m_keys[ki].setter->selectKeyframe(kId);
|
|
shun-iwasawa |
23df06 |
if (ki != 0 && segRatio[ki - 1] != 1.) {
|
|
shun-iwasawa |
23df06 |
if (m_keys[ki].setter->isSpeedInOut(kId - 1))
|
|
shun-iwasawa |
23df06 |
m_keys[ki].setter->setSpeedIn(
|
|
shun-iwasawa |
23df06 |
TPointD(m_keys[ki].orgSpeedIn.x * segRatio[ki - 1],
|
|
shun-iwasawa |
23df06 |
m_keys[ki].orgSpeedIn.y));
|
|
shun-iwasawa |
23df06 |
else if (m_keys[ki].setter->isEaseInOut(kId - 1))
|
|
shun-iwasawa |
23df06 |
m_keys[ki].setter->setEaseIn(m_keys[ki].orgSpeedIn.x *
|
|
shun-iwasawa |
23df06 |
segRatio[ki - 1]);
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
if (ki != m_keys.size() - 1 && segRatio[ki] != 1.) {
|
|
shun-iwasawa |
23df06 |
if (m_keys[ki].setter->isSpeedInOut(kId))
|
|
shun-iwasawa |
23df06 |
m_keys[ki].setter->setSpeedOut(TPointD(
|
|
shun-iwasawa |
23df06 |
m_keys[ki].orgSpeedOut.x * segRatio[ki], m_keys[ki].orgSpeedOut.y));
|
|
shun-iwasawa |
23df06 |
else if (m_keys[ki].setter->isEaseInOut(kId))
|
|
shun-iwasawa |
23df06 |
m_keys[ki].setter->setEaseOut(m_keys[ki].orgSpeedOut.x * segRatio[ki]);
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
m_previousRange = stretchedRange;
|
|
shun-iwasawa |
23df06 |
m_panel->update();
|
|
shun-iwasawa |
23df06 |
}
|
|
shun-iwasawa |
23df06 |
|
|
shun-iwasawa |
23df06 |
void StretchPointDragTool::release(QMouseEvent *e) {
|
|
shun-iwasawa |
23df06 |
for (int i = 0; i < (int)m_keys.size(); i++) delete m_keys[i].setter;
|
|
shun-iwasawa |
23df06 |
m_keys.clear();
|
|
shun-iwasawa |
23df06 |
}
|