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
}