|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tstageobjectspline.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tconst.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstroke.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstream.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tconvert.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tdoubleparam.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tdoublekeyframe.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include <qdebug></qdebug>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
PERSIST_IDENTIFIER(TStageObjectSpline, "pegbarspline")
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DEFINE_CLASS_CODE(TStageObjectSpline, 19)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
int idBaseCode = 1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// PosPathKeyframesUpdater
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// When the spline changes its shape, the PosPathKeyframesUpdater update the
|
|
Toshihiro Shimizu |
890ddd |
// PosPath channel keyframes.
|
|
Toshihiro Shimizu |
890ddd |
// If an object is close to a spline control point it must remain close to it
|
|
Toshihiro Shimizu |
890ddd |
// If the object is between two control points, then the ratio of the distances
|
|
Toshihiro Shimizu |
890ddd |
// along the spline to the two control points remain the same.
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class PosPathKeyframesUpdater {
|
|
Shinya Kitaoka |
120a6e |
std::vector<double> m_oldControlPointsLengths;</double>
|
|
Shinya Kitaoka |
120a6e |
std::vector<double> m_newControlPointsLengths;</double>
|
|
Shinya Kitaoka |
120a6e |
double m_oldSplineLength, m_newSplineLength;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
PosPathKeyframesUpdater(TStroke *oldSpline, TStroke *newSpline)
|
|
Shinya Kitaoka |
120a6e |
: m_oldSplineLength(0), m_newSplineLength(0) {
|
|
Shinya Kitaoka |
120a6e |
assert(oldSpline);
|
|
Shinya Kitaoka |
120a6e |
assert(newSpline);
|
|
Shinya Kitaoka |
120a6e |
m_oldSplineLength = oldSpline->getLength();
|
|
Shinya Kitaoka |
120a6e |
m_newSplineLength = newSpline->getLength();
|
|
Shinya Kitaoka |
120a6e |
int m;
|
|
Shinya Kitaoka |
120a6e |
m = oldSpline->getControlPointCount();
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < m; i += 4)
|
|
Shinya Kitaoka |
120a6e |
m_oldControlPointsLengths.push_back(
|
|
Shinya Kitaoka |
120a6e |
oldSpline->getLengthAtControlPoint(i));
|
|
Shinya Kitaoka |
120a6e |
m = newSpline->getControlPointCount();
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < m; i += 4)
|
|
Shinya Kitaoka |
120a6e |
m_newControlPointsLengths.push_back(
|
|
Shinya Kitaoka |
120a6e |
newSpline->getLengthAtControlPoint(i));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void update(TDoubleParam *param) {
|
|
Shinya Kitaoka |
120a6e |
assert(m_newSplineLength > 0);
|
|
Shinya Kitaoka |
120a6e |
if (m_newSplineLength <= 0) return;
|
|
Shinya Kitaoka |
120a6e |
for (int j = 0; j < param->getKeyframeCount(); j++) {
|
|
Shinya Kitaoka |
120a6e |
TDoubleKeyframe kf = param->getKeyframe(j);
|
|
Shinya Kitaoka |
120a6e |
double s = m_oldSplineLength * kf.m_value * 0.01;
|
|
Shinya Kitaoka |
120a6e |
update(s);
|
|
Shinya Kitaoka |
120a6e |
double updatedValue = s * 100.0 / m_newSplineLength;
|
|
Shinya Kitaoka |
120a6e |
kf.m_value = updatedValue;
|
|
Shinya Kitaoka |
120a6e |
param->setKeyframe(j, kf);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
void update(double &s);
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void PosPathKeyframesUpdater::update(double &s) {
|
|
Shinya Kitaoka |
120a6e |
int k = 0;
|
|
Shinya Kitaoka |
120a6e |
int oldm = (int)m_oldControlPointsLengths.size();
|
|
Shinya Kitaoka |
120a6e |
int newm = (int)m_newControlPointsLengths.size();
|
|
Shinya Kitaoka |
120a6e |
while (k < oldm && m_oldControlPointsLengths[k] <= s) k++;
|
|
Shinya Kitaoka |
120a6e |
if (k >= oldm) {
|
|
Shinya Kitaoka |
120a6e |
// all CP lengths <=s
|
|
Shinya Kitaoka |
120a6e |
if (oldm - 1 < newm)
|
|
Shinya Kitaoka |
120a6e |
s = m_newControlPointsLengths[oldm - 1];
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
s = m_newSplineLength;
|
|
Shinya Kitaoka |
120a6e |
} else if (k == 0) {
|
|
Shinya Kitaoka |
120a6e |
// all CP lengths >s
|
|
Shinya Kitaoka |
120a6e |
s = 0;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (k >= newm)
|
|
Shinya Kitaoka |
120a6e |
s = m_newSplineLength;
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
double sa = m_oldControlPointsLengths[k - 1];
|
|
Shinya Kitaoka |
120a6e |
double sb = m_oldControlPointsLengths[k];
|
|
Shinya Kitaoka |
120a6e |
double newSa = m_newControlPointsLengths[k - 1];
|
|
Shinya Kitaoka |
120a6e |
double newSb = m_newControlPointsLengths[k];
|
|
Shinya Kitaoka |
120a6e |
assert(sa <= s && s < sb);
|
|
Shinya Kitaoka |
120a6e |
if (sa >= sb) {
|
|
Shinya Kitaoka |
120a6e |
s = (newSa + newSb) * 0.5;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
s = newSa + (newSb - newSa) * (s - sa) / (sb - sa);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
// TStageObjectSpline
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TStageObjectSpline::TStageObjectSpline()
|
|
Shinya Kitaoka |
120a6e |
: TSmartObject(m_classCode)
|
|
Shinya Kitaoka |
120a6e |
, m_stroke(0)
|
|
Shinya Kitaoka |
120a6e |
, m_dagNodePos(TConst::nowhere)
|
|
Shinya Kitaoka |
120a6e |
, m_id(-1)
|
|
Shinya Kitaoka |
120a6e |
, m_idBase(std::to_string(idBaseCode++))
|
|
Shinya Kitaoka |
120a6e |
, m_name("")
|
|
Shinya Kitaoka |
120a6e |
, m_isOpened(false) {
|
|
Shinya Kitaoka |
120a6e |
double d = 30;
|
|
Shinya Kitaoka |
120a6e |
std::vector<tthickpoint> points;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
points.push_back(TPointD(0, 0));
|
|
Shinya Kitaoka |
120a6e |
points.push_back(TPointD(d, 0));
|
|
Shinya Kitaoka |
120a6e |
points.push_back(TPointD(2.0 * d, 0));
|
|
Shinya Kitaoka |
120a6e |
m_stroke = new TStroke(points);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TStageObjectSpline::~TStageObjectSpline() {
|
|
Shinya Kitaoka |
120a6e |
delete m_stroke;
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_posPathParams.size(); i++)
|
|
Shinya Kitaoka |
120a6e |
m_posPathParams[i]->release();
|
|
Shinya Kitaoka |
120a6e |
m_posPathParams.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TStageObjectSpline *TStageObjectSpline::clone() const {
|
|
Shinya Kitaoka |
120a6e |
TStageObjectSpline *clonedSpline = new TStageObjectSpline();
|
|
Shinya Kitaoka |
120a6e |
clonedSpline->m_id = m_id;
|
|
Shinya Kitaoka |
120a6e |
clonedSpline->m_name = m_name;
|
|
Shinya Kitaoka |
120a6e |
clonedSpline->m_stroke = new TStroke(*m_stroke);
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_posPathParams.size(); i++)
|
|
Shinya Kitaoka |
120a6e |
clonedSpline->m_posPathParams.push_back(
|
|
Shinya Kitaoka |
120a6e |
(TDoubleParam *)m_posPathParams[i]->clone());
|
|
Shinya Kitaoka |
120a6e |
return clonedSpline;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
const TStroke *TStageObjectSpline::getStroke() const { return m_stroke; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TStageObjectSpline::updatePosPathKeyframes(TStroke *oldSpline,
|
|
Shinya Kitaoka |
120a6e |
TStroke *newSpline) {
|
|
Shinya Kitaoka |
120a6e |
if (m_posPathParams.empty()) return;
|
|
Shinya Kitaoka |
120a6e |
PosPathKeyframesUpdater updater(oldSpline, newSpline);
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_posPathParams.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
updater.update(m_posPathParams[i]);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TStageObjectSpline::setStroke(TStroke *stroke) {
|
|
Shinya Kitaoka |
120a6e |
if (stroke != m_stroke) {
|
|
Shinya Kitaoka |
120a6e |
if (!m_posPathParams.empty() && stroke != 0 && m_stroke != 0)
|
|
Shinya Kitaoka |
120a6e |
updatePosPathKeyframes(m_stroke, stroke);
|
|
Shinya Kitaoka |
120a6e |
delete m_stroke;
|
|
Shinya Kitaoka |
120a6e |
m_stroke = stroke;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TStageObjectSpline::loadData(TIStream &is) {
|
|
Shinya Kitaoka |
120a6e |
std::vector<tthickpoint> points;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
VersionNumber tnzVersion = is.getVersion();
|
|
Shinya Kitaoka |
120a6e |
if (tnzVersion < VersionNumber(1, 16)) {
|
|
Shinya Kitaoka |
120a6e |
while (!is.eos()) {
|
|
Shinya Kitaoka |
120a6e |
TThickPoint p;
|
|
Shinya Kitaoka |
120a6e |
is >> p.x >> p.y >> p.thick;
|
|
Shinya Kitaoka |
120a6e |
points.push_back(p);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
std::string tagName;
|
|
Shinya Kitaoka |
120a6e |
while (is.matchTag(tagName)) {
|
|
Shinya Kitaoka |
120a6e |
if (tagName == "splineId")
|
|
Shinya Kitaoka |
120a6e |
is >> m_id;
|
|
Shinya Kitaoka |
120a6e |
else if (tagName == "name")
|
|
Shinya Kitaoka |
120a6e |
is >> m_name;
|
|
Shinya Kitaoka |
120a6e |
else if (tagName == "pos")
|
|
Shinya Kitaoka |
120a6e |
is >> m_dagNodePos.x >> m_dagNodePos.y;
|
|
Shinya Kitaoka |
120a6e |
else if (tagName == "isOpened") {
|
|
Shinya Kitaoka |
120a6e |
int v = 0;
|
|
Shinya Kitaoka |
120a6e |
is >> v;
|
|
Shinya Kitaoka |
120a6e |
m_isOpened = (bool)v;
|
|
Shinya Kitaoka |
120a6e |
} else if (tagName == "stroke") {
|
|
Shinya Kitaoka |
120a6e |
int i, n = 0;
|
|
Shinya Kitaoka |
120a6e |
is >> n;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < n; i++) {
|
|
Shinya Kitaoka |
120a6e |
TThickPoint p;
|
|
Shinya Kitaoka |
120a6e |
is >> p.x >> p.y >> p.thick;
|
|
Shinya Kitaoka |
120a6e |
points.push_back(p);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
is.matchEndTag();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
delete m_stroke;
|
|
Shinya Kitaoka |
120a6e |
m_stroke = new TStroke(points);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TStageObjectSpline::saveData(TOStream &os) {
|
|
Shinya Kitaoka |
120a6e |
const TStroke *stroke = getStroke();
|
|
Shinya Kitaoka |
120a6e |
os.child("splineId") << (int)m_id;
|
|
Shinya Kitaoka |
120a6e |
if (!m_name.empty()) os.child("name") << m_name;
|
|
Shinya Kitaoka |
120a6e |
os.child("isOpened") << (int)m_isOpened;
|
|
Shinya Kitaoka |
120a6e |
os.child("pos") << m_dagNodePos.x << m_dagNodePos.y;
|
|
Shinya Kitaoka |
120a6e |
os.openChild("stroke");
|
|
Shinya Kitaoka |
120a6e |
int n = stroke->getControlPointCount();
|
|
Shinya Kitaoka |
120a6e |
os << n;
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < n; i++) {
|
|
Shinya Kitaoka |
120a6e |
TThickPoint p = stroke->getControlPoint(i);
|
|
Shinya Kitaoka |
120a6e |
os << p.x << p.y << p.thick;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
os.closeChild();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TStageObjectSpline::setId(int id) { m_id = id; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int TStageObjectSpline::getId() const { return m_id; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::string TStageObjectSpline::getName() const {
|
|
Shinya Kitaoka |
120a6e |
if (m_name == "") return "Path" + std::to_string(m_id + 1);
|
|
Shinya Kitaoka |
120a6e |
return m_name;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::string TStageObjectSpline::getIconId() { return "spline" + m_idBase; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TStageObjectSpline::addParam(TDoubleParam *param) {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_posPathParams.size(); i++)
|
|
Shinya Kitaoka |
120a6e |
if (param == m_posPathParams[i]) return;
|
|
Shinya Kitaoka |
120a6e |
m_posPathParams.push_back(param);
|
|
Shinya Kitaoka |
120a6e |
param->addRef();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TStageObjectSpline::removeParam(TDoubleParam *param) {
|
|
Shinya Kitaoka |
120a6e |
std::vector<tdoubleparam *="">::iterator it =</tdoubleparam>
|
|
Shinya Kitaoka |
120a6e |
std::find(m_posPathParams.begin(), m_posPathParams.end(), param);
|
|
Shinya Kitaoka |
120a6e |
if (it == m_posPathParams.end()) return;
|
|
Shinya Kitaoka |
120a6e |
(*it)->release();
|
|
Shinya Kitaoka |
120a6e |
m_posPathParams.erase(it);
|
|
Toshihiro Shimizu |
890ddd |
}
|