|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/skeleton.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tstageobject.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tpinnedrangeset.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tstageobjectkeyframe.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/txsheet.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/stage.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TStageObjectId getAncestor(TXsheet *xsh, TStageObjectId id)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(id.isColumn());
|
|
Toshihiro Shimizu |
890ddd |
TStageObjectId parentId;
|
|
Toshihiro Shimizu |
890ddd |
while (parentId = xsh->getStageObjectParent(id), parentId.isColumn())
|
|
Toshihiro Shimizu |
890ddd |
id = parentId;
|
|
Toshihiro Shimizu |
890ddd |
return id;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int Skeleton::Bone::getColumnIndex() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return m_stageObject->getId().getIndex();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void Skeleton::Bone::setParent(Bone *parent)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_parent != parent) {
|
|
Toshihiro Shimizu |
890ddd |
m_parent = parent;
|
|
Toshihiro Shimizu |
890ddd |
parent->m_children.push_back(this);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Skeleton::Skeleton()
|
|
Toshihiro Shimizu |
890ddd |
: m_rootBone(0)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Skeleton::~Skeleton()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
clearPointerContainer(m_bones);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void Skeleton::clear()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
clearPointerContainer(m_bones);
|
|
Toshihiro Shimizu |
890ddd |
m_rootBone = 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void Skeleton::build(TXsheet *xsh, int row, int col, const std::set<int> &tempPinnedColumns)</int>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// clear
|
|
Toshihiro Shimizu |
890ddd |
m_rootBone = 0;
|
|
Toshihiro Shimizu |
890ddd |
clearPointerContainer(m_bones);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// antenato (colonna) della colonna corrente
|
|
Toshihiro Shimizu |
890ddd |
TStageObjectId ancestorId = getAncestor(xsh, TStageObjectId::ColumnId(col));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// costruisco le "ossa"
|
|
Toshihiro Shimizu |
890ddd |
std::map<tstageobjectid, *="" bone=""> boneTable;</tstageobjectid,>
|
|
Toshihiro Shimizu |
890ddd |
int columnCount = xsh->getColumnCount();
|
|
Toshihiro Shimizu |
890ddd |
int pinnedCount = 0;
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < columnCount; i++) {
|
|
Toshihiro Shimizu |
890ddd |
TStageObjectId columnId(TStageObjectId::ColumnId(i));
|
|
Toshihiro Shimizu |
890ddd |
if (getAncestor(xsh, columnId) != ancestorId)
|
|
Toshihiro Shimizu |
890ddd |
continue;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TAffine aff = xsh->getPlacement(columnId, row);
|
|
Toshihiro Shimizu |
890ddd |
TPointD center = Stage::inch * xsh->getCenter(columnId, row);
|
|
Toshihiro Shimizu |
890ddd |
TPointD p = aff * center;
|
|
Toshihiro Shimizu |
890ddd |
TStageObject *obj = xsh->getStageObject(columnId);
|
|
Toshihiro Shimizu |
890ddd |
Bone *bone = new Bone(obj, p);
|
|
Toshihiro Shimizu |
890ddd |
boneTable[columnId] = bone;
|
|
Toshihiro Shimizu |
890ddd |
m_bones.push_back(bone);
|
|
Toshihiro Shimizu |
890ddd |
if (columnId == ancestorId)
|
|
Toshihiro Shimizu |
890ddd |
m_rootBone = bone;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (obj->getPinnedRangeSet()->isPinned(row)) {
|
|
Toshihiro Shimizu |
890ddd |
pinnedCount++;
|
|
Toshihiro Shimizu |
890ddd |
bone->setPinnedStatus(Bone::PINNED);
|
|
Toshihiro Shimizu |
890ddd |
} else if (tempPinnedColumns.count(i) > 0)
|
|
Toshihiro Shimizu |
890ddd |
bone->setPinnedStatus(Bone::TEMP_PINNED);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// if no bone is pinned then the root is considered pinned
|
|
Toshihiro Shimizu |
890ddd |
if (pinnedCount == 0 && m_rootBone)
|
|
Toshihiro Shimizu |
890ddd |
m_rootBone->setPinnedStatus(Bone::PINNED);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// The skeleton could possibly be empty
|
|
Toshihiro Shimizu |
890ddd |
if (boneTable.empty()) {
|
|
Toshihiro Shimizu |
890ddd |
assert(!m_rootBone);
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// assign parents
|
|
Toshihiro Shimizu |
890ddd |
std::map<tstageobjectid, *="" bone="">::iterator it, sit;</tstageobjectid,>
|
|
Toshihiro Shimizu |
890ddd |
for (it = boneTable.begin(); it != boneTable.end(); ++it) {
|
|
Toshihiro Shimizu |
890ddd |
sit = boneTable.find(xsh->getStageObjectParent(it->first));
|
|
Toshihiro Shimizu |
890ddd |
if (sit != boneTable.end())
|
|
Toshihiro Shimizu |
890ddd |
it->second->setParent(sit->second);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// select the "active chain", i.e. the starting bone (columnIndex=col) and the ancestors
|
|
Toshihiro Shimizu |
890ddd |
it = boneTable.find(TStageObjectId::ColumnId(col));
|
|
Toshihiro Shimizu |
890ddd |
if (it != boneTable.end()) {
|
|
Toshihiro Shimizu |
890ddd |
Bone *bone = it->second;
|
|
Toshihiro Shimizu |
890ddd |
while (bone) {
|
|
Toshihiro Shimizu |
890ddd |
bone->select();
|
|
Toshihiro Shimizu |
890ddd |
bone = bone->getParent();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Skeleton::Bone *Skeleton::getBone(int index) const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(0 <= index && index < (int)m_bones.size());
|
|
Toshihiro Shimizu |
890ddd |
return m_bones[index];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Skeleton::Bone *Skeleton::getBoneByColumnIndex(int columnIndex) const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < (int)m_bones.size(); i++)
|
|
Toshihiro Shimizu |
890ddd |
if (m_bones[i]->getColumnIndex() == columnIndex)
|
|
Toshihiro Shimizu |
890ddd |
return m_bones[i];
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool Skeleton::isIKEnabled() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return m_rootBone && m_rootBone->getStageObject()->getStatus() == TStageObject::IK;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool Skeleton::hasPinnedRanges() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < getBoneCount(); i++) {
|
|
Toshihiro Shimizu |
890ddd |
TStageObject *obj = getBone(i)->getStageObject();
|
|
Toshihiro Shimizu |
890ddd |
if (obj->getPinnedRangeSet()->getRangeCount() > 0)
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void Skeleton::clearAllPinnedRanges()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < getBoneCount(); i++) {
|
|
Toshihiro Shimizu |
890ddd |
TStageObject *obj = getBone(i)->getStageObject();
|
|
Toshihiro Shimizu |
890ddd |
obj->getPinnedRangeSet()->removeAllRanges();
|
|
Toshihiro Shimizu |
890ddd |
obj->invalidate();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|