tahoma2d/toonz/sources/tnztools/plastictool_rigidity.cpp

280 lines
8.2 KiB
C++
Raw Normal View History

2016-03-19 06:57:51 +13:00
// TnzCore includes
#include "tundo.h"
#include "tgl.h"
// TnzExt includes
#include "ext/plasticdeformerstorage.h"
// TnzLib includes
#include "toonz/txshcell.h"
#include "toonz/txshsimplelevel.h"
#include "toonz/tframehandle.h"
// tcg includes
#include "tcg/tcg_point_ops.h"
// boost includes
#include <boost/noncopyable.hpp>
#include "plastictool.h"
using namespace PlasticToolLocals;
//****************************************************************************************
// Local namespace stuff
//****************************************************************************************
2016-06-15 18:43:10 +12:00
namespace {
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
enum { RIGID_IDX = 0, FLEX_IDX };
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
} // namespace
2016-03-19 06:57:51 +13:00
//****************************************************************************************
// Undo definitions
//****************************************************************************************
2016-06-15 18:43:10 +12:00
namespace {
2016-03-19 06:57:51 +13:00
class PaintRigidityUndo final : public TUndo {
2016-06-15 18:43:10 +12:00
TXshCell m_cell; //!< Affected image (cell == level + frame)
std::vector<std::map<int, double>> m_vertices; //!< Affected vertices
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
double m_paintValue; //!< Rigidity value the vertices were
//!< painted with
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
PaintRigidityUndo(const TXshCell &cell,
const std::vector<std::map<int, double>> &vertices,
double paintValue)
: m_cell(cell), m_vertices(vertices), m_paintValue(paintValue) {}
2016-06-19 20:06:29 +12:00
int getSize() const override { return 1 << 20; }
2016-06-15 18:43:10 +12:00
2016-06-19 20:06:29 +12:00
void redo() const override {
2016-06-15 18:43:10 +12:00
TXshSimpleLevel *sl =
static_cast<TXshSimpleLevel *>(m_cell.m_level.getPointer());
sl->setDirtyFlag(true);
TMeshImageP mi(sl->getFrame(m_cell.m_frameId, true));
if (!mi || mi->meshes().size() != m_vertices.size()) return;
int m, mCount = int(mi->meshes().size());
for (m = 0; m != mCount; ++m) {
TTextureMesh &mesh = *mi->meshes()[m];
std::map<int, double>::const_iterator vt, vEnd(m_vertices[m].end());
for (vt = m_vertices[m].begin(); vt != vEnd; ++vt)
mesh.vertex(vt->first).P().rigidity = m_paintValue;
}
PlasticDeformerStorage::instance()->invalidateMeshImage(
mi.getPointer(), PlasticDeformerStorage::MESH);
}
2016-06-19 20:06:29 +12:00
void undo() const override {
2016-06-15 18:43:10 +12:00
TXshSimpleLevel *sl =
static_cast<TXshSimpleLevel *>(m_cell.m_level.getPointer());
sl->setDirtyFlag(true);
TMeshImageP mi(sl->getFrame(m_cell.m_frameId, true));
if (!mi || mi->meshes().size() != m_vertices.size()) return;
int m, mCount = int(mi->meshes().size());
for (m = 0; m != mCount; ++m) {
TTextureMesh &mesh = *mi->meshes()[m];
std::map<int, double>::const_iterator vt, vEnd(m_vertices[m].end());
for (vt = m_vertices[m].begin(); vt != vEnd; ++vt)
mesh.vertex(vt->first).P().rigidity = vt->second;
}
PlasticDeformerStorage::instance()->invalidateMeshImage(
mi.getPointer(), PlasticDeformerStorage::MESH);
}
2016-03-19 06:57:51 +13:00
};
2016-06-15 18:43:10 +12:00
} // namespace
2016-03-19 06:57:51 +13:00
//****************************************************************************************
// RigidityPainter definition
//****************************************************************************************
2016-06-15 18:43:10 +12:00
namespace {
2016-03-19 06:57:51 +13:00
class RigidityPainter final : public tcg::polymorphic {
2016-06-15 18:43:10 +12:00
std::vector<std::map<int, double>>
m_oldRigidities; //!< The original values of painted vertices
double m_sqRadius, m_value; //!< Drawing parameters
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
RigidityPainter() : m_sqRadius(), m_value() {}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void startPainting(double radius, int rigidIdx);
void paint(const TPointD &pos);
void commit();
2016-03-19 06:57:51 +13:00
private:
2016-06-15 18:43:10 +12:00
void reset() {
m_sqRadius = 0.0, m_value = 0.0;
std::vector<std::map<int, double>>().swap(m_oldRigidities);
}
2016-03-19 06:57:51 +13:00
};
//------------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
void RigidityPainter::startPainting(double radius, int rigidIdx) {
m_sqRadius = sq(radius);
m_value = (rigidIdx == RIGID_IDX) ? 1e4 : 1.0;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
assert(m_oldRigidities.empty());
2016-03-19 06:57:51 +13:00
}
//------------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
void RigidityPainter::paint(const TPointD &pos) {
const TXshCell &cell = ::xshCell();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TXshSimpleLevel *sl =
dynamic_cast<TXshSimpleLevel *>(cell.m_level.getPointer());
if (!sl) return;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TMeshImageP meshImg = TTool::getImage(true);
if (!meshImg) return;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// Soil the level - schedules it for save
sl->setDirtyFlag(true);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// Paint all mesh vertices inside the circle with center pos and given radius
const std::vector<TTextureMeshP> &meshes = meshImg->meshes();
int m, mCount = int(meshImg->meshes().size());
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
m_oldRigidities.resize(mCount);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
for (m = 0; m != mCount; ++m) {
TTextureMesh &mesh = *meshes[m];
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int v, vCount = mesh.verticesCount();
for (v = 0; v != vCount; ++v) {
RigidPoint &vxPos = mesh.vertex(v).P();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
if (tcg::point_ops::dist2(pos, (const TPointD &)vxPos) < m_sqRadius) {
if (!m_oldRigidities[m].count(v))
m_oldRigidities[m][v] = vxPos.rigidity;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
vxPos.rigidity = m_value;
}
}
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
PlasticDeformerStorage::instance()->invalidateMeshImage(
meshImg.getPointer(), PlasticDeformerStorage::MESH);
2016-03-19 06:57:51 +13:00
}
//------------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
void RigidityPainter::commit() {
TUndoManager::manager()->add(
new PaintRigidityUndo(::xshCell(), m_oldRigidities, m_value));
reset();
2016-03-19 06:57:51 +13:00
}
2016-06-15 18:43:10 +12:00
} // namespace
2016-03-19 06:57:51 +13:00
//****************************************************************************************
// PlasticTool functions
//****************************************************************************************
std::unique_ptr<tcg::polymorphic> PlasticTool::createRigidityPainter() {
return std::unique_ptr<tcg::polymorphic>(new RigidityPainter);
2016-03-19 06:57:51 +13:00
}
//------------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
void PlasticTool::mouseMove_rigidity(const TPointD &pos, const TMouseEvent &e) {
// Track mouse position
m_pos = pos; // Needs to be done now - ensures m_pos is valid
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
invalidate();
2016-03-19 06:57:51 +13:00
}
//------------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
void PlasticTool::leftButtonDown_rigidity(const TPointD &pos,
const TMouseEvent &) {
// Track mouse position
m_pressedPos = m_pos = pos;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
RigidityPainter *painter =
static_cast<RigidityPainter *>(m_rigidityPainter.get());
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
painter->startPainting(m_thickness.getValue(), m_rigidValue.getIndex());
painter->paint(m_pos);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
invalidate();
2016-03-19 06:57:51 +13:00
}
//------------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
void PlasticTool::leftButtonDrag_rigidity(const TPointD &pos,
const TMouseEvent &) {
// Track mouse position
m_pos = pos;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
RigidityPainter *painter =
static_cast<RigidityPainter *>(m_rigidityPainter.get());
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
painter->paint(m_pos);
invalidate();
2016-03-19 06:57:51 +13:00
}
//------------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
void PlasticTool::leftButtonUp_rigidity(const TPointD &pos,
const TMouseEvent &) {
// Track mouse position
m_pos = pos;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
RigidityPainter *painter =
static_cast<RigidityPainter *>(m_rigidityPainter.get());
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
painter->commit();
2016-03-19 06:57:51 +13:00
}
//------------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
void PlasticTool::addContextMenuActions_rigidity(QMenu *menu) {}
2016-03-19 06:57:51 +13:00
//------------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
void PlasticTool::draw_rigidity() {
if (TTool::getApplication()->getCurrentFrame()->isEditingScene()) {
// In the rigidity case, we're editing the mesh level - so the implicit
// transformation affine loaded by OpenGL gets multiplied by the level's
// dpi scale. We have to revert the scale before showing column-related
// data.
const TPointD &dpiScale = TTool::getViewer()->getDpiScale();
glPushMatrix();
{
tglMultMatrix(TScale(1.0 / dpiScale.x, 1.0 / dpiScale.y));
double pixelSize = sqrt(tglGetPixelSize2());
// Draw original skeleton
const PlasticSkeletonP &skeleton = this->skeleton();
if (skeleton) {
drawOnionSkinSkeletons_build(pixelSize);
drawSkeleton(*skeleton, pixelSize);
drawSelections(m_sd, *skeleton, pixelSize);
}
}
glPopMatrix();
}
// Draw a circle centered at m_pos with m_thickness radius
glColor3f(1.0f, 0.0f, 0.0f); // Red
tglDrawCircle(m_pos, m_thickness.getValue());
2016-03-19 06:57:51 +13:00
}