#pragma once
#ifndef SKELETON_INCLUDED
#define SKELETON_INCLUDED
#include "tgeometry.h"
#include <set>
#undef DVAPI
#undef DVVAR
#ifdef TOONZLIB_EXPORTS
#define DVAPI DV_EXPORT_API
#define DVVAR DV_EXPORT_VAR
#else
#define DVAPI DV_IMPORT_API
#define DVVAR DV_IMPORT_VAR
#endif
class TXsheet;
class TStageObject;
//! The Skeleton is the data structure used by the Skeleton Tool
class DVAPI Skeleton {
public:
class DVAPI Bone {
public:
enum PinnedStatus { FREE, PINNED, TEMP_PINNED };
Bone(TStageObject *pegbar, const TPointD ¢er)
: m_parent(0)
, m_stageObject(pegbar)
, m_center(center)
, m_selected(false)
, m_pinnedStatus(FREE) {}
void setParent(Bone *parent);
Bone *getParent() const { return m_parent; }
int getChildCount() const { return (int)m_children.size(); }
Bone *getChild(int index) const {
return 0 <= index && index < getChildCount() ? m_children[index] : 0;
}
TStageObject *getStageObject() const { return m_stageObject; }
int getColumnIndex() const;
const TPointD &getCenter() const { return m_center; }
void select(bool selected = true) { m_selected = selected; }
bool isSelected() const { return m_selected; }
PinnedStatus getPinnedStatus() const { return m_pinnedStatus; }
void setPinnedStatus(PinnedStatus pinnedStatus) {
m_pinnedStatus = pinnedStatus;
}
private:
Bone *m_parent;
std::vector<Bone *> m_children;
TStageObject *m_stageObject;
TPointD m_center; // position of the rotation center of the stageobject,
// i.e. the "joint"
bool m_selected; // true if the bone belongs to the active chain (i.e.
// handle <-> pinned points)
PinnedStatus m_pinnedStatus;
}; // class Bone
private:
std::vector<Bone *> m_bones;
Bone *m_rootBone;
public:
Skeleton();
~Skeleton();
//! create a skeleton containing 'col'.
//! tempPinnedColumns contains the column indices of the temporarily pinned
//! bones
void build(TXsheet *xsh, int row, int col,
const std::set<int> &tempPinnedColumns = std::set<int>());
//! reset the skeleton
void clear();
int getBoneCount() const { return m_bones.size(); }
Bone *getBone(int index) const;
Bone *getBoneByColumnIndex(int columnIndex) const;
//! the root is the ancestor of each bone in the skeleton
Bone *getRootBone() const { return m_rootBone; }
//! helper functions. see TPinnedRangeSet
//! the root status is TStageObject::IK
bool isIKEnabled() const;
//! Some bone has a not empty pinned range
bool hasPinnedRanges() const;
void clearAllPinnedRanges();
};
#endif