Merge remote-tracking branch 'upstream/master' into tahoma

This commit is contained in:
Jeremy Bullock 2020-05-16 18:28:14 -06:00
commit f5fd4a4e34
7 changed files with 177 additions and 112 deletions

View file

@ -65,7 +65,7 @@ public:
\sa rotate270
*/
template <class T>
inline TPointT<T> rotate90(const TPointT<T> &p) // counterclockwise
inline TPointT<T> rotate90(const TPointT<T> &p) // 90 counterclockwise
{
return TPointT<T>(-p.y, p.x);
}
@ -76,7 +76,7 @@ inline TPointT<T> rotate90(const TPointT<T> &p) // counterclockwise
\sa rotate90
*/
template <class T>
inline TPointT<T> rotate270(const TPointT<T> &p) // clockwise
inline TPointT<T> rotate270(const TPointT<T> &p) // 90 clockwise
{
return TPointT<T>(p.y, -p.x);
}
@ -84,7 +84,7 @@ inline TPointT<T> rotate270(const TPointT<T> &p) // clockwise
/*!
\relates TPointT
*/
template <class T> // prodotto scalare
template <class T> // Scalar(dot) Product
inline T operator*(const TPointT<T> &a, const TPointT<T> &b) {
return a.x * b.x + a.y * b.y;
}
@ -542,11 +542,11 @@ template class DVAPI TDimensionT<double>;
//=============================================================================
//! Specifies the corners of a rectangle.
/*!\arg \a x0 specifies the x-coordinate of the bottom-left corner of a
rectangle.
\arg \a y0 specifies the y-coordinate of the bottom-left corner of a rectangle.
\arg \a x1 specifies the x-coordinate of the upper-right corner of a rectangle.
\arg \a y1 specifies the y-coordinate of the upper-right corner of a rectangle.
/*!
x0 specifies the x-coordinate of the bottom-left corner of a rectangle.
y0 specifies the y-coordinate of the bottom-left corner of a rectangle.
x1 specifies the x-coordinate of the upper-right corner of a rectangle.
y1 specifies the y-coordinate of the upper-right corner of a rectangle.
*/
template <class T>
class DVAPI TRectT {
@ -561,14 +561,18 @@ if x0==y1 && y0==y1 and rect is a TRectD then rect is empty */
TRectT();
TRectT(T _x0, T _y0, T _x1, T _y1) : x0(_x0), y0(_y0), x1(_x1), y1(_y1){};
TRectT(const TRectT &rect)
: x0(rect.x0), y0(rect.y0), x1(rect.x1), y1(rect.y1){};
TRectT(const TPointT<T> &p0, const TPointT<T> &p1) // non importa l'ordine
: x0(std::min((T)p0.x, (T)p1.x)),
y0(std::min((T)p0.y, (T)p1.y)),
x1(std::max((T)p0.x, (T)p1.x)),
y1(std::max((T)p0.y, (T)p1.y)){};
TRectT(const TPointT<T> &bottomLeft, const TDimensionT<T> &d);
TRectT(const TDimensionT<T> &d);
void empty();
@ -588,15 +592,15 @@ TRectI is empty if x0>x1 || y0>y1 */
TPointT<T> getP11() const { return TPointT<T>(x1, y1); };
//! Returns the union of two source rectangles.
/*!The union is the smallest rectangle that contains both source rectangles.
*/
//!The union is the smallest rectangle that contains both source rectangles.
TRectT<T> operator+(const TRectT<T> &rect) const { // unione
if (isEmpty())
return rect;
else if (rect.isEmpty())
return *this;
else
return TRectT<T>(std::min((T)x0, (T)rect.x0), std::min((T)y0, (T)rect.y0),
return TRectT<T>(std::min((T)x0, (T)rect.x0),
std::min((T)y0, (T)rect.y0),
std::max((T)x1, (T)rect.x1),
std::max((T)y1, (T)rect.y1));
};
@ -607,10 +611,8 @@ TRectI is empty if x0>x1 || y0>y1 */
return *this = *this * rect;
};
/*!Returns the intersection of two existing rectangles.
The intersection is the largest rectangle contained in both existing rectangles.
*/
//!Returns the intersection of two existing rectangles.
//The intersection is the largest rectangle contained in both existing rectangles.
TRectT<T> operator*(const TRectT<T> &rect) const { // intersezione
if (isEmpty() || rect.isEmpty())
return TRectT<T>();
@ -622,7 +624,7 @@ The intersection is the largest rectangle contained in both existing rectangles.
std::min((T)y1, (T)rect.y1));
};
TRectT<T> &operator+=(const TPointT<T> &p) { // spostamento
TRectT<T> &operator+=(const TPointT<T> &p) { // shift
x0 += p.x;
y0 += p.y;
x1 += p.x;
@ -691,6 +693,7 @@ template class DVAPI TRectT<double>;
\relates TRectT
Convert a TRectD into a TRect
*/
inline TRect convert(const TRectD &r) {
return TRect((int)(r.x0 + 0.5), (int)(r.y0 + 0.5), (int)(r.x1 + 0.5),
(int)(r.y1 + 0.5));
@ -707,8 +710,8 @@ inline TRectD convert(const TRect &r) { return TRectD(r.x0, r.y0, r.x1, r.y1); }
\relates TPointT
*/
inline TRectD boundingBox(const TPointD &p0, const TPointD &p1) {
return TRectD(std::min(p0.x, p1.x), std::min(p0.y, p1.y),
std::max(p0.x, p1.x), std::max(p0.y, p1.y));
return TRectD(std::min(p0.x, p1.x), std::min(p0.y, p1.y), // bottom left
std::max(p0.x, p1.x), std::max(p0.y, p1.y)); // top right
}
/*!
\relates TRectT
@ -733,6 +736,7 @@ inline TRectD boundingBox(const TPointD &p0, const TPointD &p1,
//-----------------------------------------------------------------------------
// TRectT is a rectangle that uses thick points
template <>
inline TRectT<int>::TRectT() : x0(0), y0(0), x1(-1), y1(-1) {}
template <>
@ -754,6 +758,8 @@ inline void TRectT<int>::empty() {
x0 = y0 = 0;
x1 = y1 = -1;
}
// Is the adding of one here to account for the thickness?
template <>
inline int TRectT<int>::getLx() const {
return x1 >= x0 ? x1 - x0 + 1 : 0;
@ -846,21 +852,15 @@ extern DVVAR const TRectI infiniteRectI;
//=============================================================================
//! This is the base class for the affine transformations.
/*!
This class performs basic manipulations of affine
transformations.
An affine transformation is a linear transformation followed by
a translation.
<p>
\f$ x \mapsto \bf{A} x + b \f$
</p>
<p>
\f$ \bf{A} \f$ is a \f$ 2X2 \f$ matrix.
In a matrix notation:
<p> \f$ \left(\begin{array}{c} \vec{y} \\ 1 \end{array}\right) =
\left( \begin{array}{cc} \bf{A} & \vec{b} \\ \vec{0} & 1
\end{array}\right)
\left(\begin{array}{c}\vec{x} \\ 1 \end{array} \right) \f$ </p>
*/
This class performs basic manipulations of affine transformations.
An affine transformation is a linear transformation followed by a translation.
[a11, a12, a13]
[a21, a22, a23]
a13 and a23 represent translation (moving sideways or up and down)
the other 4 handle rotation, scale and shear
*/
class DVAPI TAffine {
public:
double a11, a12, a13;
@ -891,7 +891,7 @@ public:
Assignment operator.
*/
TAffine &operator=(const TAffine &a);
/*Sposto in tgeometry.cpp
/*Moved to tgeometry.cpp
{
a11 = a.a11; a12 = a.a12; a13 = a.a13;
a21 = a.a21; a22 = a.a22; a23 = a.a23;
@ -905,7 +905,7 @@ return *this;
*/
TAffine operator*(const TAffine &b) const;
/*Sposto in tgeometry.cpp
/*Moved to in tgeometry.cpp
{
return TAffine (
a11 * b.a11 + a12 * b.a21,
@ -919,7 +919,7 @@ a21 * b.a13 + a22 * b.a23 + a23);
*/
TAffine operator*=(const TAffine &b);
/*Sposto in tgeometry.cpp
/*Moved to tgeometry.cpp
{
return *this = *this * b;
};
@ -930,7 +930,7 @@ return *this = *this * b;
*/
TAffine inv() const;
/*Sposto in tgeometry.cpp
/*Moved to tgeometry.cpp
{
if(a12 == 0.0 && a21 == 0.0)
{

View file

@ -18,12 +18,7 @@
#endif
//******************** IK Utility *********************
//
// Di seguito le classi VectorRn e MatrixRmn
// TODO: Se possibile cambiare e usare le STL
//
//
//****************************************************
//*****************************************************
//***********************************************************************
// CLASS VectorRN
@ -683,15 +678,15 @@ public:
void Reset();
private:
IKSkeleton *skeleton; // skeletro associato a questa matrice Jacobiana
IKSkeleton *skeleton; // skeleton associated with this Jacobian matrix
std::vector<TPointD> target;
int nEffector; // Numero di end effectors
int nJoint; // Numero di Joints
int nRow; // righe matrice J (= 2*numero di end effectors)
int nCol; // numero di colonne di J
int nEffector; // Number of end effectors
int nJoint; // Number of Joints
int nRow; // matrix rows J(= 2 * number of end effectors)
int nCol; // number of columns of J
MatrixRmn
Jend; // matrice Jacobiana basata sulle posizioni degli end effectors
Jend; // Jacobian matrix based on the positions of the end effectors
MatrixRmn Jtarget;
MatrixRmn Jnorms; // Norms of 2-vectors in active Jacobian (solo SDLS)
@ -709,10 +704,10 @@ private:
VectorRn dPreTheta; // (vale solo per SDLS)
// Parametri per pseudorinversa
// Parameters for pseudorinverse
static const double PseudoInverseThresholdFactor;
// Paremetri pe il metodo Damped Least Squares
// Paremeters for the Damped Least Squares method
static const double DefaultDampingLambda;
double DampingLambda;
double DampingLambdaSq;

View file

@ -22,8 +22,8 @@ public:
enum Purpose { JOINT, EFFECTOR };
IKNode() : m_parent(0), m_pos() {
r = TPointD(0.0, 1.0); // r sara' aggiornato quando il nodo sara; inserito
// nello skeleton
r = TPointD(0.0, 1.0); // r will be updated when the node is added
// in the skeleton
theta = 0.0;
m_parent = 0;
}
@ -70,7 +70,7 @@ public:
}
bool isFrozen() const { return freezed; }
void freeze() { freezed = true; } // mantiene l'angolo theta costante
void freeze() { freezed = true; } // keeps the theta angle constant
void unFreeze() { freezed = false; }
private:
@ -79,20 +79,20 @@ private:
TPointD m_pos;
Purpose m_purpose;
int m_seqNumJoint; // indice del Joint nella sequenza di Joint
int m_seqNumEffector; // indice dell'Effector nella sequenza di Effectors
int m_seqNumJoint; // Joint index in the Joint sequence
int m_seqNumEffector; // index of the effector in the sequence of effectors
TPointD r; // Posizione relativa
TPointD s; // Posizione Globale
// TPointD w; // Rotazione Globale dell'asse
TPointD r; // Relative position
TPointD s; // Global position
// TPointD w; // Global axis rotation
double theta; // angolo del joint (radianti)
double theta0; // angolo iniziale del joint (radianti)
double minTheta; // limite inferiore angolo
double maxTheta; // limite superiore angolo
double restAngle; // angolo esplementare
double theta; // joint angle(radians)
double theta0; // initial angle of the joint(radians)
double minTheta; // lower angle limit
double maxTheta; // high angle limit
double restAngle;
bool freezed; // Se vero l'angolo è blocccato
bool freezed;
};
#endif // IKNODE_H

View file

@ -181,6 +181,7 @@ DragPositionTool::DragPositionTool(SkeletonTool *tool)
void DragPositionTool::leftButtonDown(const TPointD &pos, const TMouseEvent &) {
start();
m_firstPos = pos;
m_firstDrag = true;
}
//------------------------------------------------------------
@ -188,6 +189,11 @@ void DragPositionTool::leftButtonDown(const TPointD &pos, const TMouseEvent &) {
void DragPositionTool::leftButtonDrag(const TPointD &pos,
const TMouseEvent &e) {
TPointD delta = pos - m_firstPos;
if (m_firstDrag && (delta.x > 2.0 || delta.y > 2.0)) {
m_firstPos = pos;
delta = TPointD(0.0, 0.0);
m_firstDrag = false;
}
if (e.isShiftPressed()) {
if (fabs(delta.x) > fabs(delta.y))
delta.y = 0;
@ -419,12 +425,21 @@ void ParentChangeTool::draw() { getTool()->drawHooks(); }
//
//------------------------------------------------------------
namespace {
// This needs some clarification.
namespace {
class Graph {
// local variables defined below are:
// Nodes m_nodes;
// std::map<int, int> m_leaves;
public:
typedef std::set<int> Links;
typedef Links::const_iterator LinkIter;
// the second part of the nodes map is a set if ints
typedef std::map<int, Links> Nodes;
typedef Nodes::const_iterator NodeIter;
typedef std::map<int, int> LeaveTable;
@ -433,11 +448,16 @@ public:
Graph() {}
int touch(int id) {
// insert an empty node if not found
if (m_nodes.count(id) == 0) m_nodes[id] = Links();
return id;
}
// check if a node is found in m_nodes
bool isNode(int id) const { return m_nodes.count(id) > 0; }
int getNodeCount() const { return (int)m_nodes.size(); }
void link(int a, int b) {
touch(a);
touch(b);
@ -448,12 +468,15 @@ public:
NodeIter it = m_nodes.find(a);
return it == m_nodes.end() ? false : it->second.count(b);
}
const Links &getLinks(int id) const {
static const Links empty;
NodeIter it = m_nodes.find(id);
return it == m_nodes.end() ? empty : it->second;
}
int getLinkCount(int id) const { return (int)getLinks(id).size(); }
int getFirstLink(int id) const {
const Links &links = getLinks(id);
return links.empty() ? -1 : *(links.begin());
@ -462,6 +485,9 @@ public:
NodeIter begin() const { return m_nodes.begin(); }
NodeIter end() const { return m_nodes.end(); }
// Wht is a leave?
// m_leaves is a std map of int int
bool isLeave(int id) const { return m_leaves.count(id); }
enum LeaveType {
@ -470,14 +496,20 @@ public:
CHILD_END = 0x4,
PARENT_END = 0x8
};
int getLeaveType(int id) const {
LeaveIter it = m_leaves.find(id);
return it == m_leaves.end() ? 0 : it->second;
}
void setLeaveType(int id, int type) { m_leaves[id] = type; }
// This gets rid of a node.
void remove(int id) {
NodeIter it = m_nodes.find(id);
if (it != m_nodes.end()) {
// iterate over the links
for (LinkIter j = it->second.begin(); j != it->second.end(); ++j)
m_nodes[*j].erase(id);
m_nodes.erase(it->first);
@ -499,15 +531,21 @@ bool hasPinned(const Skeleton::Bone *bone, const Skeleton::Bone *prevBone) {
if (!bone) return false;
bool isHandle = prevBone == 0;
bool isChild = prevBone != 0 && prevBone == bone->getParent();
if (bone->getPinnedStatus() != Skeleton::Bone::FREE) return true;
if (bone->getParent() && bone->getParent() != prevBone &&
hasPinned(bone->getParent(), bone))
return true;
hasPinned(bone->getParent(), bone)) {
return true;
}
for (int i = 0; i < bone->getChildCount(); i++)
if (bone->getChild(i) != prevBone)
if (hasPinned(bone->getChild(i), bone)) return true;
for (int i = 0; i < bone->getChildCount(); i++) {
if (bone->getChild(i) != prevBone) {
if (hasPinned(bone->getChild(i), bone)) {
return true;
}
}
}
return false;
}
@ -518,7 +556,10 @@ bool hasPinned(const Skeleton::Bone *bone, const Skeleton::Bone *prevBone) {
bool addToActiveChain(Graph &tree, const Skeleton::Bone *bone,
const Skeleton::Bone *prevBone) {
if (!bone) return false;
// The handle is what you grabbed
bool isHandle = prevBone == 0;
bool isChild = prevBone != 0 && prevBone == bone->getParent();
bool isParent = prevBone != 0 && prevBone->getParent() == bone;
int pinnedStatus = bone->getPinnedStatus();
@ -527,22 +568,33 @@ bool addToActiveChain(Graph &tree, const Skeleton::Bone *bone,
bool isTempPinned = pinnedStatus == Skeleton::Bone::TEMP_PINNED;
bool propagate = false;
if (!isChild && isFree)
if (bone->getParent())
propagate |= addToActiveChain(tree, bone->getParent(), bone);
// Go up the chain from what you grabbed and add bones
if (!isChild && isFree) {
if (bone->getParent()) {
propagate |= addToActiveChain(tree, bone->getParent(), bone);
}
}
std::vector<int> children;
if (isHandle || isFree)
for (int i = 0; i < bone->getChildCount(); i++)
if (bone->getChild(i) != prevBone)
propagate |= addToActiveChain(tree, bone->getChild(i), bone);
// Once you reach the top parent, add the other children
if (isHandle || isFree) {
for (int i = 0; i < bone->getChildCount(); i++) {
if (bone->getChild(i) != prevBone) {
propagate |= addToActiveChain(tree, bone->getChild(i), bone);
}
}
}
bool insert = false;
if (isHandle) // the handle must be added anyway
insert = true;
else if (isChild) // add child if it's pinned or if some gran-child has been
// added
insert = !isFree || propagate;
else if (isTempPinned) {
// parent temp pinned are normally added, but if another branch is pinned we
// are not
@ -656,6 +708,7 @@ public:
TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
TTool::getApplication()->getCurrentObject()->notifyObjectIdChanged(false);
}
void redo() const override {
TXsheet *xsh = TTool::getApplication()->getCurrentXsheet()->getXsheet();
for (int i = 0; i < (int)m_nodes.size(); i++) {
@ -689,7 +742,7 @@ IKTool::IKTool(SkeletonTool *tool, TTool::Viewer *viewer, Skeleton *skeleton,
, m_pos()
, m_columnIndex(columnIndex)
, m_valid(false)
, m_IHateIK(false)
, m_frameOnNewPin(false)
, m_foot(0)
, m_firstFoot(0)
, m_undo(0) {}
@ -708,14 +761,13 @@ bool IKTool::isParentOf(int columnIndex, int childColumnIndex) const {
}
//------------------------------------------------------------
// This is a beast.
void IKTool::initEngine(const TPointD &pos) {
m_valid = false;
m_engine.clear();
m_joints.clear();
// m_skeleton->getRootBone()->getStageObject()->setStatus(TStageObject::IK);
// build the active chain (bounded by m_columnIndex and pinned nodes)
Graph chain;
addToActiveChain(chain, m_skeleton->getBoneByColumnIndex(m_columnIndex), 0);
@ -739,8 +791,7 @@ void IKTool::initEngine(const TPointD &pos) {
}
// search the foot (i.e. the pinned node). if there are no pinned node find
// the first
// temp-pinned
// the first temp-pinned
int foot = -1;
for (Graph::NodeIter it = chain.begin(); it != chain.end(); ++it)
if (chain.isLeave(it->first)) {
@ -763,8 +814,7 @@ void IKTool::initEngine(const TPointD &pos) {
}
// if the handle is a terminal node (i.e. just one link) and the next node is
// a child
// move the handle to the next node
// a child move the handle to the next node
int handle = m_columnIndex;
if (chain.getLinkCount(handle) == 1) {
int nextNode = chain.getFirstLink(handle);
@ -774,8 +824,6 @@ void IKTool::initEngine(const TPointD &pos) {
}
}
//
// "reverse" the tree to suit the IKEngine convention
std::vector<std::pair<int, Skeleton::Bone *>> stack;
std::vector<int> done;
@ -858,7 +906,11 @@ void IKTool::initEngine(const TPointD &pos) {
//------------------------------------------------------------
// TODO cambiare questo nome; aggiungere due righe di spiegazione
// This sets foot placement data
// and checks if the current frame is the start
// of a new pinned center
// The name of this function should be changed once it
// actually works. Until then, the name is fitting.
void IKTool::computeIHateIK() {
std::vector<TStageObject *> objs;
for (int i = 0; i < m_skeleton->getBoneCount(); i++)
@ -866,24 +918,30 @@ void IKTool::computeIHateIK() {
int n = (int)objs.size();
int frame = TTool::getApplication()->getCurrentFrame()->getFrame();
m_foot = m_firstFoot = 0;
m_IHateIK = false;
m_frameOnNewPin = false;
// this just finds the first pin
int i;
for (i = 0; i < n && !objs[i]->getPinnedRangeSet()->isPinned(frame); i++) {
}
for (i = 0; i < n && !objs[i]->getPinnedRangeSet()->isPinned(frame); i++) {}
if (i == n) return;
// this makes m_foot to be the current pin
m_foot = objs[i];
// check to see if this frame is the start of a new pin
const TPinnedRangeSet::Range *range =
m_foot->getPinnedRangeSet()->getRange(frame);
if (!range || range->first != frame) return;
m_IHateIK = true;
m_frameOnNewPin = true;
int firstFrame = frame - 1;
m_firstFoot = m_foot;
// the frame is the start of a new pinned frame, find the previous pin
for (;;) {
for (i = 0; i < n && !objs[i]->getPinnedRangeSet()->isPinned(firstFrame);
i++) {
}
i++) {}
if (i == n) break;
m_firstFoot = objs[i];
range = m_firstFoot->getPinnedRangeSet()->getRange(firstFrame);
@ -891,6 +949,7 @@ void IKTool::computeIHateIK() {
firstFrame = range->first - 1;
if (firstFrame < 0) break;
}
m_footPlacement = m_foot->getPlacement(frame);
m_firstFootPlacement = m_firstFoot->getPinnedRangeSet()->getPlacement();
}
@ -934,7 +993,7 @@ void IKTool::storeOldValues() {
}
}
//------------------------------------------------------------
// This is called on movement of the mouse with button down
void IKTool::apply() {
if (!m_valid) return;
TStageObject *rootObj = m_skeleton->getRootBone()->getStageObject();
@ -943,7 +1002,7 @@ void IKTool::apply() {
for (int i = 0; i < (int)m_joints.size(); i++)
m_undo->addNode(m_joints[i].m_bone->getStageObject()->getId());
if (m_IHateIK && m_firstFoot) {
if (m_frameOnNewPin && m_firstFoot) {
m_undo->setFirstFootId(m_firstFoot->getId());
m_undo->setFirstFootOldPlacement(
m_firstFoot->getPinnedRangeSet()->getPlacement());
@ -963,7 +1022,7 @@ void IKTool::apply() {
param->setValue(frame, theta);
}
m_skeleton->getRootBone()->getStageObject()->invalidate();
if (m_IHateIK) {
if (m_frameOnNewPin) {
TStageObject *rootObj = m_skeleton->getRootBone()->getStageObject();
rootObj->setStatus(TStageObject::XY);
rootObj->invalidate();
@ -1012,7 +1071,7 @@ void IKTool::leftButtonDrag(const TPointD &p, const TMouseEvent &e) {
void IKTool::leftButtonUp(const TPointD &p, const TMouseEvent &e) {
if (m_undo) {
if (m_IHateIK && m_firstFoot)
if (m_frameOnNewPin && m_firstFoot)
m_undo->setFirstFootNewPlacement(
m_firstFoot->getPinnedRangeSet()->getPlacement());
TUndoManager::manager()->add(m_undo);

View file

@ -86,6 +86,7 @@ public:
class DragPositionTool final : public DragChannelTool {
TPointD m_firstPos;
bool m_firstDrag = false;
public:
DragPositionTool(SkeletonTool *tool);
@ -161,9 +162,10 @@ class IKTool final : public DragTool {
int m_columnIndex;
IKEngine m_engine;
bool m_valid;
bool m_rootInvolved;
TAffine m_footPlacement, m_firstFootPlacement;
TStageObject *m_foot, *m_firstFoot;
bool m_IHateIK;
bool m_frameOnNewPin;
IKToolUndo *m_undo;
struct Joint {

View file

@ -78,7 +78,7 @@ inline std::string removeTrailingH(std::string handle) {
//
//------------------------------------------------------------
// return true iff column ancestorIndex is column descentIndex or its parent or
// return true if column ancestorIndex is column descentIndex or its parent or
// the parent of the parent, etc.
static bool isAncestorOf(int ancestorIndex, int descendentIndex) {
TStageObjectId ancestorId = TStageObjectId::ColumnId(ancestorIndex);
@ -93,7 +93,7 @@ static bool isAncestorOf(int ancestorIndex, int descendentIndex) {
static void getHooks(std::vector<HookData> &hooks, TXsheet *xsh, int row,
int col, TPointD dpiScale) {
// nota. hook position is in the coordinate system of the parent object.
// note. hook position is in the coordinate system of the parent object.
// a inch is Stage::inch
TXshCell cell = xsh->getCell(row, col);
@ -342,7 +342,7 @@ void SkeletonTool::leftButtonDown(const TPointD &ppos, const TMouseEvent &e) {
int selectedDevice = pick(e.m_pos);
// cambio drawing
// change drawing
if (selectedDevice == TD_ChangeDrawing ||
selectedDevice == TD_IncrementDrawing ||
selectedDevice == TD_DecrementDrawing) {
@ -356,7 +356,7 @@ void SkeletonTool::leftButtonDown(const TPointD &ppos, const TMouseEvent &e) {
return;
}
// click su un hook: attacca la colonna corrente tramite quell'hook
// click on a hook: attach the current column via that hook
if (TD_Hook <= selectedDevice && selectedDevice < TD_Hook + 50) {
TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
TStageObjectId objId = TStageObjectId::ColumnId(currentColumnIndex);
@ -381,7 +381,7 @@ void SkeletonTool::leftButtonDown(const TPointD &ppos, const TMouseEvent &e) {
bool justSelected = false;
if (m_device < 0) {
// nessun gadget cliccato. Eventualmente seleziono la colonna
// No gadget clicked. Select the column
std::vector<int> columnIndexes;
getViewer()->posToColumnIndexes(e.m_pos, columnIndexes, getPixelSize() * 5,
false);
@ -414,12 +414,21 @@ void SkeletonTool::leftButtonDown(const TPointD &ppos, const TMouseEvent &e) {
// lock/unlock: modalita IK
if (TD_LockStageObject <= m_device && m_device < TD_LockStageObject + 1000) {
Skeleton* skeleton = new Skeleton();
buildSkeleton(*skeleton, currentColumnIndex);
int columnIndex = m_device - TD_LockStageObject;
int frame = app->getCurrentFrame()->getFrame();
togglePinnedStatus(columnIndex, frame, e.isShiftPressed());
invalidate();
m_dragTool = 0;
return;
int frame = app->getCurrentFrame()->getFrame();
if (skeleton->getBoneByColumnIndex(columnIndex) == skeleton->getRootBone()) {
app->getCurrentColumn()->setColumnIndex(columnIndex);
m_device = TD_Translation;
}
else if (e.isShiftPressed()) {
togglePinnedStatus(columnIndex, frame, e.isShiftPressed());
invalidate();
m_dragTool = 0;
return;
}
else return;
}
switch (m_device) {
@ -989,7 +998,7 @@ void SkeletonTool::drawIKBone(const TPointD &a, const TPointD &b) {
//-------------------------------------------------------------------
void SkeletonTool::computeMagicLinks() {
// TODO: spostare qui il calcolo dei magic link
// TODO: move the calculation of the magic links here
}
//-------------------------------------------------------------------

View file

@ -18,7 +18,7 @@ int IKEngine::addJoint(const TPointD &pos, int indexParent) {
m_skeleton.setParent(index, indexParent);
return index;
}
// la root deve coincidere con un punto bloccato!
// The root must be a pinned point!
void IKEngine::setRoot(const TPointD &pos) {
m_skeleton.addNode(new IKNode());
m_skeleton.setNode(0, pos, IKNode::JOINT);
@ -64,7 +64,7 @@ void IKEngine::drag(TPointD &pos) {
// se lo scheletro è vuoto non succede nulla
if (m_skeleton.getNodeCount() == 0) return;
// afferro l'ultimo punto della catena
// Grab the last point of the chain
int indexDrag = m_skeleton.getNodeCount() - 1;
if (m_skeleton.getNode(indexDrag)->getParent()->IsEffector()) return;
m_skeleton.setPurpose(indexDrag, IKNode::EFFECTOR);