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