|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// TnzCore includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tundo.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// TnzLib includes
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tobjecthandle.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "plastictool.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
using namespace PlasticToolLocals;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Undo definitions
|
|
Toshihiro Shimizu |
890ddd |
//****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
d1f6c4 |
class AnimateValuesUndo final : public TUndo {
|
|
Shinya Kitaoka |
120a6e |
int m_row, m_col; //!< Xsheet coordinates
|
|
Shinya Kitaoka |
120a6e |
int m_v; //!< Moved vertex
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
SkDKey m_oldValues, m_newValues; //!< Keyframe values
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
AnimateValuesUndo(int v) : m_row(::row()), m_col(::column()), m_v(v) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Again, not accurate. We should get in the details of SkDF... So, let's say
|
|
Shinya Kitaoka |
120a6e |
// around 10 kB - max 10k instances in the standard undos pool.
|
|
Shinya Kitaoka |
473e70 |
int getSize() const override { return 10 << 10; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
473e70 |
void redo() const override {
|
|
Shinya Kitaoka |
120a6e |
PlasticTool::TemporaryActivation tempActivate(m_row, m_col);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (m_v >= 0) l_plasticTool.setSkeletonSelection(m_v);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
l_suspendParamsObservation =
|
|
Shinya Kitaoka |
120a6e |
true; // Coalesce params change notifications into one
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
l_plasticTool.deformation()->deleteKeyframe(m_row - 1);
|
|
Shinya Kitaoka |
120a6e |
l_plasticTool.deformation()->setKeyframe(m_newValues);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
l_suspendParamsObservation = false;
|
|
Shinya Kitaoka |
120a6e |
l_plasticTool.onChange();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
473e70 |
void undo() const override {
|
|
Shinya Kitaoka |
120a6e |
PlasticTool::TemporaryActivation tempActivate(m_row, m_col);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (m_v >= 0) l_plasticTool.setSkeletonSelection(m_v);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
l_suspendParamsObservation =
|
|
Shinya Kitaoka |
120a6e |
true; // Coalesce params change notifications into one
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
l_plasticTool.deformation()->deleteKeyframe(
|
|
Shinya Kitaoka |
120a6e |
m_row - 1); // Yep. Typical frame/row shift... xD
|
|
Shinya Kitaoka |
120a6e |
l_plasticTool.deformation()->setKeyframe(m_oldValues);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
l_suspendParamsObservation = false;
|
|
Shinya Kitaoka |
120a6e |
l_plasticTool.onChange();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// PlasticTool functions
|
|
Toshihiro Shimizu |
890ddd |
//****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void PlasticTool::mouseMove_animate(const TPointD &pos, const TMouseEvent &me) {
|
|
Shinya Kitaoka |
120a6e |
// Track mouse position
|
|
Shinya Kitaoka |
120a6e |
m_pos = pos; // Needs to be done now - ensures m_pos is valid
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_svHigh = m_seHigh = -1; // Reset highlighted primitives
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (m_sd) {
|
|
Shinya Kitaoka |
120a6e |
double d, highlightRadius = getPixelSize() * HIGHLIGHT_DISTANCE;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Look for nearest vertex
|
|
Shinya Kitaoka |
120a6e |
int v = deformedSkeleton().closestVertex(pos, &d);
|
|
Shinya Kitaoka |
120a6e |
if (v >= 0 && d < highlightRadius) m_svHigh = v;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
invalidate();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void PlasticTool::leftButtonDown_animate(const TPointD &pos,
|
|
Shinya Kitaoka |
120a6e |
const TMouseEvent &me) {
|
|
Shinya Kitaoka |
120a6e |
// Track mouse position
|
|
Shinya Kitaoka |
120a6e |
m_pressedPos = m_pos = pos;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
setSkeletonSelection(m_svHigh);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (m_svSel.hasSingleObject()) {
|
|
Shinya Kitaoka |
120a6e |
// Store original vertex position and keyframe values
|
|
Shinya Kitaoka |
120a6e |
m_pressedVxsPos =
|
|
Shinya Kitaoka |
120a6e |
std::vector<tpointd>(1, deformedSkeleton().vertex(m_svSel).P());</tpointd>
|
|
Shinya Kitaoka |
120a6e |
m_sd->getKeyframeAt(frame(), m_pressedSkDF);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void PlasticTool::leftButtonDrag_animate(const TPointD &pos,
|
|
Shinya Kitaoka |
120a6e |
const TMouseEvent &me) {
|
|
Shinya Kitaoka |
120a6e |
// Track mouse position
|
|
Shinya Kitaoka |
120a6e |
m_pos = pos;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_sd && m_svSel.hasSingleObject() &&
|
|
Shinya Kitaoka |
120a6e |
m_svSel > 0) // Avoid move if vertex is root
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
l_suspendParamsObservation = true; // Automatic params notification happen
|
|
Shinya Kitaoka |
120a6e |
// twice (1 x param) - dealing with it manually
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double frame = ::frame();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// First, retrieve selected vertex's deformation
|
|
Shinya Kitaoka |
120a6e |
SkVD *vd = m_sd->vertexDeformation(::skeletonId(), m_svSel);
|
|
Shinya Kitaoka |
120a6e |
assert(vd);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Move selected branch
|
|
Shinya Kitaoka |
120a6e |
if (m_keepDistance.getValue()) {
|
|
Shinya Kitaoka |
120a6e |
::setKeyframe(vd->m_params[SkVD::ANGLE],
|
|
Shinya Kitaoka |
120a6e |
frame); // Set a keyframe for it. It must be done
|
|
Shinya Kitaoka |
120a6e |
// to set the correct function interpolation
|
|
Shinya Kitaoka |
120a6e |
// type and other stuff.
|
|
Shinya Kitaoka |
120a6e |
m_sd->updateAngle(*skeleton(), deformedSkeleton(), frame, m_svSel, pos);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
::setKeyframe(vd->m_params[SkVD::ANGLE],
|
|
Shinya Kitaoka |
120a6e |
frame); // Same here. NOTE: Not setting a frame on
|
|
Shinya Kitaoka |
120a6e |
::setKeyframe(vd->m_params[SkVD::DISTANCE],
|
|
Shinya Kitaoka |
120a6e |
frame); // vd directly due to SkVD::SO
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_sd->updatePosition(*skeleton(), deformedSkeleton(), frame, m_svSel,
|
|
Shinya Kitaoka |
120a6e |
pos);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
l_suspendParamsObservation = false;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// onChange(); // Due to
|
|
Shinya Kitaoka |
120a6e |
// a nasty Function Editor dependency,
|
|
Shinya Kitaoka |
120a6e |
// it's better to call the following directly
|
|
Shinya Kitaoka |
120a6e |
m_deformedSkeleton.invalidate();
|
|
Shinya Kitaoka |
120a6e |
invalidate();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void PlasticTool::leftButtonUp_animate(const TPointD &pos,
|
|
Shinya Kitaoka |
120a6e |
const TMouseEvent &me) {
|
|
Shinya Kitaoka |
120a6e |
// Track mouse position
|
|
Shinya Kitaoka |
120a6e |
m_pos = pos;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (m_svSel.hasSingleObject() && m_dragged) {
|
|
Shinya Kitaoka |
120a6e |
// Set a keyframe to each skeleton vertex, if that was requested
|
|
Shinya Kitaoka |
120a6e |
if (m_globalKey.getValue())
|
|
Shinya Kitaoka |
120a6e |
::setKeyframe(m_sd, ::frame()); // Already invokes keyframes rebuild
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
stageObject()->updateKeyframes(); // Otherwise, must be explicit
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Add a corresponding undo
|
|
Shinya Kitaoka |
120a6e |
AnimateValuesUndo *undo = new AnimateValuesUndo(m_svSel);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
undo->m_oldValues = m_pressedSkDF;
|
|
Shinya Kitaoka |
120a6e |
m_sd->getKeyframeAt(frame(), undo->m_newValues);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->add(undo);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// This is needed to refresh the xsheet (there may be new keyframes)
|
|
Shinya Kitaoka |
120a6e |
TTool::getApplication()->getCurrentObject()->notifyObjectIdChanged(false);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// In case one of the vertices is attached (as a hook) to an external
|
|
Shinya Kitaoka |
120a6e |
// position,
|
|
Shinya Kitaoka |
120a6e |
// we need to update the whole skeleton according to the updated vertex.
|
|
Shinya Kitaoka |
120a6e |
updateMatrix();
|
|
Shinya Kitaoka |
120a6e |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void PlasticTool::addContextMenuActions_animate(QMenu *menu) {
|
|
Shinya Kitaoka |
120a6e |
bool ret = true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (!m_svSel.isEmpty()) {
|
|
Shinya Kitaoka |
120a6e |
QAction *setKey = menu->addAction(tr("Set Key"));
|
|
Shinya Kitaoka |
120a6e |
ret = ret && connect(setKey, SIGNAL(triggered()), &l_plasticTool,
|
|
Shinya Kitaoka |
120a6e |
SLOT(setKey_undo()));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
QAction *setRestKey = menu->addAction(tr("Set Rest Key"));
|
|
Shinya Kitaoka |
120a6e |
ret = ret && connect(setRestKey, SIGNAL(triggered()), &l_plasticTool,
|
|
Shinya Kitaoka |
120a6e |
SLOT(setRestKey_undo()));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
QAction *setGlobalKey = menu->addAction(tr("Set Global Key"));
|
|
Shinya Kitaoka |
120a6e |
ret = ret && connect(setGlobalKey, SIGNAL(triggered()), &l_plasticTool,
|
|
Shinya Kitaoka |
120a6e |
SLOT(setGlobalKey_undo()));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
QAction *setGlobalRestKey = menu->addAction(tr("Set Global Rest Key"));
|
|
Shinya Kitaoka |
120a6e |
ret = ret && connect(setGlobalRestKey, SIGNAL(triggered()), &l_plasticTool,
|
|
Shinya Kitaoka |
120a6e |
SLOT(setGlobalRestKey_undo()));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
menu->addSeparator();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
assert(ret);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void PlasticTool::keyFunc_undo(void (PlasticTool::*keyFunc)()) {
|
|
Shinya Kitaoka |
120a6e |
assert(m_svSel.objects().size() <= 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
double frame = ::frame();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
AnimateValuesUndo *undo = new AnimateValuesUndo(m_svSel);
|
|
Shinya Kitaoka |
120a6e |
m_sd->getKeyframeAt(frame, undo->m_oldValues);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
(this->*keyFunc)();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_sd->getKeyframeAt(frame, undo->m_newValues);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->add(undo);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void PlasticTool::draw_animate() {
|
|
Shinya Kitaoka |
120a6e |
double pixelSize = getPixelSize();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
PlasticSkeleton &deformedSkeleton = this->deformedSkeleton();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Draw deformed skeleton
|
|
Shinya Kitaoka |
120a6e |
if (m_sd) {
|
|
Shinya Kitaoka |
120a6e |
drawOnionSkinSkeletons_animate(pixelSize);
|
|
Shinya Kitaoka |
120a6e |
drawSkeleton(deformedSkeleton, pixelSize);
|
|
Shinya Kitaoka |
120a6e |
drawSelections(m_sd, deformedSkeleton, pixelSize);
|
|
Shinya Kitaoka |
120a6e |
drawAngleLimits(m_sd, m_skelId, m_svSel, pixelSize);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
drawHighlights(m_sd, &deformedSkeleton, pixelSize);
|
|
Toshihiro Shimizu |
890ddd |
}
|