Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
#include "tgl.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tenv.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/tstageobjectcmd.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzimageutils.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshcolumn.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsimplelevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobjecttree.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobjectspline.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzscene.h"
Toshihiro Shimizu 890ddd
#include "toonz/stage.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshcell.h"
Toshihiro Shimizu 890ddd
#include "toonz/dpiscale.h"
Toshihiro Shimizu 890ddd
#include "toonz/skeleton.h"
Toshihiro Shimizu 890ddd
#include "toonz/tscenehandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tobjecthandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tpinnedrangeset.h"
Toshihiro Shimizu 890ddd
#include "toonz/tframehandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheethandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/stageobjectutil.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzQt includes
Toshihiro Shimizu 890ddd
#include "toonzqt/selection.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/selectioncommandids.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzTools includes
Toshihiro Shimizu 890ddd
#include "tools/tool.h"
Toshihiro Shimizu 890ddd
#include "tools/cursors.h"
Toshihiro Shimizu 890ddd
#include "tools/toolutils.h"
Toshihiro Shimizu 890ddd
#include "tw/keycodes.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qcoreapplication> // Qt translation support</qcoreapplication>
Toshihiro Shimizu 890ddd
#include <qpainter></qpainter>
Toshihiro Shimizu 890ddd
#include <qglwidget></qglwidget>
Toshihiro Shimizu 890ddd
#include <qpainterpath></qpainterpath>
Toshihiro Shimizu 890ddd
#include <qstring></qstring>
Toshihiro Shimizu 890ddd
#include <qimage></qimage>
Toshihiro Shimizu 890ddd
#include <qfont></qfont>
Toshihiro Shimizu 890ddd
#include <qfontmetrics></qfontmetrics>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "skeletonsubtools.h"
Toshihiro Shimizu 890ddd
#include "skeletontool.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace SkeletonSubtools;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TEnv::IntVar SkeletonGlobalKeyFrame("SkeletonToolGlobalKeyFrame", 0);
Toshihiro Shimizu 890ddd
TEnv::IntVar SkeletonInverseKinematics("SkeletonToolInverseKinematics", 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define BUILD_SKELETON L"Build Skeleton"
Toshihiro Shimizu 890ddd
#define ANIMATE L"Animate"
Toshihiro Shimizu 890ddd
#define INVERSE_KINEMATICS L"Inverse Kinematics"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const double alpha = 0.4;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using SkeletonSubtools::HookData;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline std::string removeTrailingH(std::string handle)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (handle.find("H") == 0)
Toshihiro Shimizu 890ddd
		return handle.substr(1);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return handle;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//============================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// util
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// return true iff column ancestorIndex is column descentIndex or its parent or the parent of the parent, etc.
Toshihiro Shimizu 890ddd
bool isAncestorOf(int ancestorIndex, int descendentIndex)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TStageObjectId ancestorId = TStageObjectId::ColumnId(ancestorIndex);
Toshihiro Shimizu 890ddd
	TStageObjectId descendentId = TStageObjectId::ColumnId(descendentIndex);
Toshihiro Shimizu 890ddd
	TXsheet *xsh = TTool::getApplication()->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
	while (descendentId != ancestorId && descendentId.isColumn())
Toshihiro Shimizu 890ddd
		descendentId = xsh->getStageObjectParent(descendentId);
Toshihiro Shimizu 890ddd
	return descendentId == ancestorId;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void getHooks(std::vector<hookdata> &hooks, TXsheet *xsh, int row, int col, TPointD dpiScale)</hookdata>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// nota. hook position is in the coordinate system of the parent object.
Toshihiro Shimizu 890ddd
	// a inch is Stage::inch
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXshCell cell = xsh->getCell(row, col);
Toshihiro Shimizu 890ddd
	if (!cell.m_level)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TStageObjectId columnId = TStageObjectId::ColumnId(col);
Toshihiro Shimizu 890ddd
	// handle is the current handle (pivot) of the column. It can be H1,H2,... or A,B,C,...
Toshihiro Shimizu 890ddd
	std::string handle = xsh->getStageObject(TStageObjectId::ColumnId(col))->getHandle();
Toshihiro Shimizu 890ddd
	bool handleIsHook = handle.find("H") == 0;
Toshihiro Shimizu 890ddd
	TAffine aff = xsh->getPlacement(columnId, row);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// imageDpiAff represent the scale factor between the image and the camera
Toshihiro Shimizu 890ddd
	// derived by dpi match (i.e. ignoring geometric transformation)
Toshihiro Shimizu 890ddd
	// cameraPos = imageDpiAff * imagePos
Toshihiro Shimizu 890ddd
	TAffine imageDpiAff;
Toshihiro Shimizu 890ddd
	if (cell.m_level->getSimpleLevel())
Toshihiro Shimizu 890ddd
		imageDpiAff = getDpiAffine(cell.m_level->getSimpleLevel(), cell.m_frameId, true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// center (inches)
Toshihiro Shimizu 890ddd
	TPointD center = xsh->getCenter(columnId, row); // getHooks
Toshihiro Shimizu 890ddd
	if (handleIsHook)
Toshihiro Shimizu 890ddd
		center = TPointD(0, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// add the hook #0 (i.e. the regular center)
Toshihiro Shimizu 890ddd
	hooks.push_back(HookData(xsh, col, 0, aff * TScale(Stage::inch) * center));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// add the regular hooks
Toshihiro Shimizu 890ddd
	HookSet *hookSet = cell.m_level->getHookSet();
Toshihiro Shimizu 890ddd
	if (hookSet && hookSet->getHookCount() > 0) {
Toshihiro Shimizu 890ddd
		for (int j = 0; j < hookSet->getHookCount(); j++) {
Toshihiro Shimizu 890ddd
			Hook *hook = hookSet->getHook(j);
Toshihiro Shimizu 890ddd
			if (hook && !hook->isEmpty()) {
Toshihiro Shimizu 890ddd
				TPointD pos = hook->getAPos(cell.m_frameId);
Toshihiro Shimizu 890ddd
				pos = aff * imageDpiAff * pos;
Toshihiro Shimizu 890ddd
				hooks.push_back(HookData(xsh, col, j + 1, pos));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void getConnectedColumns(std::set<int> &connectedColumns, TXsheet *xsh, int col)</int>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TStageObjectId id;
Toshihiro Shimizu 890ddd
	// insert col and all column ancestors
Toshihiro Shimizu 890ddd
	id = TStageObjectId::ColumnId(col);
Toshihiro Shimizu 890ddd
	do {
Toshihiro Shimizu 890ddd
		connectedColumns.insert(id.getIndex());
Toshihiro Shimizu 890ddd
		id = xsh->getStageObjectParent(id);
Toshihiro Shimizu 890ddd
	} while (id.isColumn());
Toshihiro Shimizu 890ddd
	// for each column
Toshihiro Shimizu 890ddd
	for (int i = 0; i < xsh->getColumnCount(); i++) {
Toshihiro Shimizu 890ddd
		id = TStageObjectId::ColumnId(i);
Toshihiro Shimizu 890ddd
		std::vector<tstageobjectid> stack;</tstageobjectid>
Toshihiro Shimizu 890ddd
		// find a column ancestor already connected; put all the column ancestors in stack
Toshihiro Shimizu 890ddd
		while (id.isColumn() && connectedColumns.count(id.getIndex()) == 0) {
Toshihiro Shimizu 890ddd
			stack.push_back(id);
Toshihiro Shimizu 890ddd
			id = xsh->getStageObjectParent(id);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (id.isColumn()) {
Toshihiro Shimizu 890ddd
			// the stack is connected
Toshihiro Shimizu 890ddd
			for (int j = 0; j < (int)stack.size(); j++)
Toshihiro Shimizu 890ddd
				connectedColumns.insert(stack[j].getIndex());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool canShowBone(Skeleton::Bone *bone, TXsheet *xsh, int row)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TStageObjectId id = bone->getStageObject()->getId();
Toshihiro Shimizu 890ddd
	if (!xsh->getCell(row, id.getIndex()).isEmpty() && xsh->getColumn(id.getIndex())->isCamstandVisible())
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < bone->getChildCount(); i++) {
Toshihiro Shimizu 890ddd
		if (canShowBone(bone->getChild(i), xsh, row))
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
HookData::HookData(TXsheet *xsh, int columnIndex, int hookId, const TPointD &pos)
Toshihiro Shimizu 890ddd
	: m_columnIndex(columnIndex), m_hookId(hookId), m_pos(pos), m_isPivot(false)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::string handle = xsh->getStageObject(TStageObjectId::ColumnId(columnIndex))->getHandle();
Toshihiro Shimizu 890ddd
	if (m_hookId == 0) {
Toshihiro Shimizu 890ddd
		// if the current handle is a hook the the hook#0 should be the default center, i.e. B
Toshihiro Shimizu 890ddd
		if (handle.find("H") == 0)
Toshihiro Shimizu 890ddd
			m_name = "B";
Toshihiro Shimizu 890ddd
		else {
Toshihiro Shimizu 890ddd
			m_name = handle;
Toshihiro Shimizu 890ddd
			m_isPivot = true;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		m_name = toString(m_hookId);
Toshihiro Shimizu 890ddd
		m_isPivot = "H" + m_name == handle;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
enum ToolDevice {
Toshihiro Shimizu 890ddd
	TD_None = -1,
Toshihiro Shimizu 890ddd
	TD_Translation = 1,
Toshihiro Shimizu 890ddd
	TD_Rotation,
Toshihiro Shimizu 890ddd
	TD_Center,
Toshihiro Shimizu 890ddd
	TD_ChangeParent,
Toshihiro Shimizu 890ddd
	TD_ChangeDrawing,
Toshihiro Shimizu 890ddd
	TD_IncrementDrawing,
Toshihiro Shimizu 890ddd
	TD_DecrementDrawing,
Toshihiro Shimizu 890ddd
	TD_InverseKinematics,
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TD_Hook = 10000,
Toshihiro Shimizu 890ddd
	TD_LockStageObject = 20000,
Toshihiro Shimizu 890ddd
	TD_MagicLink = 30000,
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TD_Test = 100000
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//============================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// SkeletonTool
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
SkeletonTool skeletonTool;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
SkeletonTool::SkeletonTool()
Toshihiro Shimizu 890ddd
	: TTool("T_Skeleton"), m_active(false), m_device(TD_None), m_mode("Mode:"), m_showOnlyActiveSkeleton("Show Only Active Skeleton", false), m_globalKeyframes("Global Key", false), m_dragTool(0), m_firstTime(true), m_currentFrame(-1), m_parentProbe(), m_parentProbeEnabled(false), m_otherColumn(-1), m_otherColumnBBoxAff(), m_otherColumnBBox(), m_labelPos(0, 0), m_label("")
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	bind(TTool::CommonLevels);
Toshihiro Shimizu 890ddd
	m_prop.bind(m_mode);
Toshihiro Shimizu 890ddd
	m_prop.bind(m_globalKeyframes);
Toshihiro Shimizu 890ddd
	m_prop.bind(m_showOnlyActiveSkeleton);
Toshihiro Shimizu 890ddd
	m_mode.setId("SkeletonMode");
Toshihiro Shimizu 890ddd
	m_globalKeyframes.setId("GlobalKey");
Toshihiro Shimizu 890ddd
	m_showOnlyActiveSkeleton.setId("ShowOnlyActiveSkeleton");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_mode.addValue(BUILD_SKELETON);
Toshihiro Shimizu 890ddd
	m_mode.addValue(ANIMATE);
Toshihiro Shimizu 890ddd
	m_mode.addValue(INVERSE_KINEMATICS);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_commandHandler = new CommandHandler();
Toshihiro Shimizu 890ddd
	m_commandHandler->setTempPinnedSet(&m_temporaryPinnedColumns);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
SkeletonTool::~SkeletonTool()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_dragTool;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
bool SkeletonTool::onPropertyChanged(std::string propertyName)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	SkeletonGlobalKeyFrame = (int)(m_globalKeyframes.getValue());
Toshihiro Shimizu 890ddd
	// SkeletonInverseKinematics=(int)(m_ikEnabled.getValue());
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool SkeletonTool::isGlobalKeyframesEnabled() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_globalKeyframes.getValue();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::updateTranslation()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// m_ikEnabled.setQStringName(tr("Inverse Kinematics"));
Toshihiro Shimizu 890ddd
	m_showOnlyActiveSkeleton.setQStringName(tr("Show Only Active Skeleton"));
Toshihiro Shimizu 890ddd
	m_globalKeyframes.setQStringName(tr("Global Key"));
Toshihiro Shimizu 890ddd
	m_mode.setQStringName(tr("Mode:"));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool SkeletonTool::doesApply() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTool::Application *app = TTool::getApplication();
Toshihiro Shimizu 890ddd
	TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
	assert(xsh);
Toshihiro Shimizu 890ddd
	TStageObjectId objId = app->getCurrentObject()->getObjectId();
Toshihiro Shimizu 890ddd
	if (objId.isColumn()) {
Toshihiro Shimizu 890ddd
		TXshColumn *column = xsh->getColumn(objId.getIndex());
Toshihiro Shimizu 890ddd
		if (column && column->getSoundColumn())
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::mouseMove(const TPointD &, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int selectedDevice = pick(e.m_pos);
Toshihiro Shimizu 890ddd
	if (selectedDevice != m_device) {
Toshihiro Shimizu 890ddd
		m_device = selectedDevice;
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::leftButtonDown(const TPointD &ppos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_otherColumn = -1;
Toshihiro Shimizu 890ddd
	m_otherColumnBBox = TRectD();
Toshihiro Shimizu 890ddd
	m_otherColumnBBoxAff = TAffine();
Toshihiro Shimizu 890ddd
	m_labelPos = TPointD(0, 0);
Toshihiro Shimizu 890ddd
	m_label = "";
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->beginBlock();
Toshihiro Shimizu 890ddd
	if (!doesApply())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(m_dragTool == 0);
Toshihiro Shimizu 890ddd
	m_dragTool = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTool::Application *app = TTool::getApplication();
Toshihiro Shimizu 890ddd
	int currentColumnIndex = app->getCurrentColumn()->getColumnIndex();
Toshihiro Shimizu 890ddd
	TXsheet *xsh = app->getCurrentScene()->getScene()->getXsheet();
Toshihiro Shimizu 890ddd
	TPointD pos = ppos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int selectedDevice = pick(e.m_pos);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// cambio drawing
Toshihiro Shimizu 890ddd
	if (selectedDevice == TD_ChangeDrawing ||
Toshihiro Shimizu 890ddd
		selectedDevice == TD_IncrementDrawing ||
Toshihiro Shimizu 890ddd
		selectedDevice == TD_DecrementDrawing) {
Toshihiro Shimizu 890ddd
		int d = 0;
Toshihiro Shimizu 890ddd
		if (selectedDevice == TD_IncrementDrawing)
Toshihiro Shimizu 890ddd
			d = 1;
Toshihiro Shimizu 890ddd
		else if (selectedDevice == TD_DecrementDrawing)
Toshihiro Shimizu 890ddd
			d = -1;
Toshihiro Shimizu 890ddd
		m_dragTool = new ChangeDrawingTool(this, d);
Toshihiro Shimizu 890ddd
		m_dragTool->leftButtonDown(ppos, e);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// click su un hook: attacca la colonna corrente tramite quell'hook
Toshihiro Shimizu 890ddd
	if (TD_Hook <= selectedDevice && selectedDevice < TD_Hook + 50) {
Toshihiro Shimizu 890ddd
		TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
		TStageObjectId objId = TStageObjectId::ColumnId(currentColumnIndex);
Toshihiro Shimizu 890ddd
		TPointD p0 = getCurrentColumnMatrix() * TPointD(0, 0);
Toshihiro Shimizu 890ddd
		HookData hook(xsh, currentColumnIndex, selectedDevice - TD_Hook, p0);
Toshihiro Shimizu 890ddd
		TStageObjectCmd::setHandle(objId, hook.getHandle(), app->getCurrentXsheet());
Toshihiro Shimizu 890ddd
		app->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// magic link
Toshihiro Shimizu 890ddd
	if (TD_MagicLink <= selectedDevice && selectedDevice < TD_MagicLink + (int)m_magicLinks.size()) {
Toshihiro Shimizu 890ddd
		magicLink(selectedDevice - TD_MagicLink);
Toshihiro Shimizu 890ddd
		app->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_device = selectedDevice;
Toshihiro Shimizu 890ddd
	bool justSelected = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_device < 0) {
Toshihiro Shimizu 890ddd
		// nessun gadget cliccato. Eventualmente seleziono la colonna
Toshihiro Shimizu 890ddd
		std::vector<int> columnIndexes;</int>
Toshihiro Shimizu 890ddd
		getViewer()->posToColumnIndexes(e.m_pos, columnIndexes, getPixelSize() * 5, false);
Toshihiro Shimizu 890ddd
		if (!columnIndexes.empty()) {
Toshihiro Shimizu 890ddd
			int columnIndex;
Toshihiro Shimizu 890ddd
			columnIndex = columnIndexes.back();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (columnIndex >= 0 && columnIndex != currentColumnIndex) {
Toshihiro Shimizu 890ddd
				if (!isColumnLocked(columnIndex)) {
Toshihiro Shimizu 890ddd
					pos = getMatrix() * pos;
Toshihiro Shimizu 890ddd
					app->getCurrentColumn()->setColumnIndex(columnIndex);
Toshihiro Shimizu 890ddd
					updateMatrix();
Toshihiro Shimizu 890ddd
					currentColumnIndex = columnIndex;
Toshihiro Shimizu 890ddd
					justSelected = true;
Toshihiro Shimizu 890ddd
					pos = getMatrix().inv() * pos;
Toshihiro Shimizu 890ddd
				} else {
Toshihiro Shimizu 890ddd
					m_label = "Column is locked";
Toshihiro Shimizu 890ddd
					m_labelPos = pos;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_device < 0) {
Toshihiro Shimizu 890ddd
		if (m_mode.getValue() == INVERSE_KINEMATICS)
Toshihiro Shimizu 890ddd
			m_device = TD_InverseKinematics;
Toshihiro Shimizu 890ddd
		else if (m_mode.getValue() == ANIMATE)
Toshihiro Shimizu 890ddd
			m_device = TD_Rotation;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// lock/unlock: modalita IK
Toshihiro Shimizu 890ddd
	if (TD_LockStageObject <= m_device && m_device < TD_LockStageObject + 1000) {
Toshihiro Shimizu 890ddd
		int columnIndex = m_device - TD_LockStageObject;
Toshihiro Shimizu 890ddd
		int frame = app->getCurrentFrame()->getFrame();
Toshihiro Shimizu 890ddd
		togglePinnedStatus(columnIndex, frame, e.isShiftPressed());
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
		m_dragTool = 0;
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	switch (m_device) {
Toshihiro Shimizu 890ddd
	case TD_Center:
Toshihiro Shimizu 890ddd
		m_dragTool = new DragCenterTool(this);
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case TD_Translation:
Toshihiro Shimizu 890ddd
		m_dragTool = new DragPositionTool(this);
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case TD_Rotation:
Toshihiro Shimizu 890ddd
		m_dragTool = new DragRotationTool(this, justSelected);
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case TD_ChangeParent:
Toshihiro Shimizu 890ddd
		m_dragTool = new ParentChangeTool(this, getViewer());
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case TD_InverseKinematics: {
Toshihiro Shimizu 890ddd
		Skeleton *skeleton = new Skeleton();
Toshihiro Shimizu 890ddd
		buildSkeleton(*skeleton, currentColumnIndex);
Toshihiro Shimizu 890ddd
		m_dragTool = new IKTool(this, getViewer(), skeleton, currentColumnIndex);
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_dragTool) {
Toshihiro Shimizu 890ddd
		m_dragTool->leftButtonDown(pos, e);
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_dragTool) {
Toshihiro Shimizu 890ddd
		m_dragTool->leftButtonDrag(pos, e);
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_label = "";
Toshihiro Shimizu 890ddd
	m_labelPos = TPointD(0, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_dragTool) {
Toshihiro Shimizu 890ddd
		m_dragTool->leftButtonUp(pos, e);
Toshihiro Shimizu 890ddd
		delete m_dragTool;
Toshihiro Shimizu 890ddd
		m_dragTool = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
		TTool::getApplication()->getCurrentObject()->notifyObjectIdChanged(false); // Keyframes navigator reads this
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (m_device == TD_IncrementDrawing || m_device == TD_DecrementDrawing || m_device == TD_ChangeDrawing)
Toshihiro Shimizu 890ddd
		m_device = pick(e.m_pos);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		m_device = -1;
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->endBlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool SkeletonTool::keyDown(int key, TUINT32 flags, const TPoint &pos)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ChangeDrawingTool tool(this, 0);
Toshihiro Shimizu 890ddd
	if (key == TwConsts::TK_UpArrow)
Toshihiro Shimizu 890ddd
		tool.changeDrawing(1);
Toshihiro Shimizu 890ddd
	else if (key == TwConsts::TK_DownArrow)
Toshihiro Shimizu 890ddd
		tool.changeDrawing(-1);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TogglePinnedStatusUndo : public TUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	SkeletonTool *m_tool;
Toshihiro Shimizu 890ddd
	std::set<int> m_oldTemp, m_newTemp;</int>
Toshihiro Shimizu 890ddd
	int m_columnIndex, m_oldColumnIndex;
Toshihiro Shimizu 890ddd
	std::pair<int, int=""> m_newRange, m_oldRange;</int,>
Toshihiro Shimizu 890ddd
	TAffine m_oldPlacement, m_newPlacement;
Toshihiro Shimizu 890ddd
	std::vector<std::pair<tstageobjectid, tstageobject::keyframe="">> m_keyframes;</std::pair<tstageobjectid,>
Toshihiro Shimizu 890ddd
	int m_frame;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	TogglePinnedStatusUndo(SkeletonTool *tool, int frame)
Toshihiro Shimizu 890ddd
		: m_tool(tool), m_oldTemp(), m_newTemp(), m_columnIndex(-1), m_oldColumnIndex(-1), m_newRange(0, -1), m_oldRange(0, -1), m_frame(frame)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void addBoneId(const TStageObjectId &id)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TStageObject *stageObject = getXsheet()->getStageObject(id);
Toshihiro Shimizu 890ddd
		if (stageObject) {
Toshihiro Shimizu 890ddd
			TStageObject::Keyframe k = stageObject->getKeyframe(m_frame);
Toshihiro Shimizu 890ddd
			m_keyframes.push_back(std::make_pair(id, k));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void setOldRange(int columnIndex, int first, int second, const TAffine &placement)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_oldColumnIndex = columnIndex;
Toshihiro Shimizu 890ddd
		m_oldRange = std::make_pair(first, second);
Toshihiro Shimizu 890ddd
		m_oldPlacement = placement;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void setNewRange(int columnIndex, int first, int second, const TAffine &placement)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_columnIndex = columnIndex;
Toshihiro Shimizu 890ddd
		m_newRange = std::make_pair(first, second);
Toshihiro Shimizu 890ddd
		m_newPlacement = placement;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void setOldTemp(const std::set<int> &oldTemp) { m_oldTemp = oldTemp; }</int>
Toshihiro Shimizu 890ddd
	void setNewTemp(const std::set<int> &newTemp) { m_newTemp = newTemp; }</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TStageObject *getStageObject(int columnIndex) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return TTool::getApplication()
Toshihiro Shimizu 890ddd
			->getCurrentXsheet()
Toshihiro Shimizu 890ddd
			->getXsheet()
Toshihiro Shimizu 890ddd
			->getStageObject(TStageObjectId::ColumnId(columnIndex));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPinnedRangeSet *getRangeSet(int columnIndex) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return getStageObject(columnIndex)->getPinnedRangeSet();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *getXsheet() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return TTool::getApplication()->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void notify() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_tool->invalidate();
Toshihiro Shimizu 890ddd
		TXsheet *xsh = getXsheet();
Toshihiro Shimizu 890ddd
		int index = m_columnIndex;
Toshihiro Shimizu 890ddd
		if (index < 0)
Toshihiro Shimizu 890ddd
			index = m_oldColumnIndex;
Toshihiro Shimizu 890ddd
		if (index >= 0) {
Toshihiro Shimizu 890ddd
			TStageObjectId id = TStageObjectId::ColumnId(index);
Toshihiro Shimizu 890ddd
			TStageObjectId parentId;
Toshihiro Shimizu 890ddd
			while (parentId = xsh->getStageObjectParent(id), parentId.isColumn())
Toshihiro Shimizu 890ddd
				id = parentId;
Toshihiro Shimizu 890ddd
			xsh->getStageObject(id)->invalidate();
Toshihiro Shimizu 890ddd
			TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
			TTool::getApplication()->getCurrentObject()->notifyObjectIdChanged(false);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void undo() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_tool->setTemporaryPinnedColumns(m_oldTemp);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_columnIndex >= 0)
Toshihiro Shimizu 890ddd
			getRangeSet(m_columnIndex)->removeRange(m_newRange.first, m_newRange.second);
Toshihiro Shimizu 890ddd
		if (m_oldColumnIndex >= 0) {
Toshihiro Shimizu 890ddd
			TPinnedRangeSet *rangeSet = getRangeSet(m_oldColumnIndex);
Toshihiro Shimizu 890ddd
			rangeSet->setRange(m_oldRange.first, m_oldRange.second);
Toshihiro Shimizu 890ddd
			rangeSet->setPlacement(m_oldPlacement);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		TXsheet *xsh = getXsheet();
Toshihiro Shimizu 890ddd
		for (int i = 0; i < (int)m_keyframes.size(); i++) {
Toshihiro Shimizu 890ddd
			TStageObject *stageObject = getXsheet()->getStageObject(m_keyframes[i].first);
Toshihiro Shimizu 890ddd
			if (!stageObject)
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
			stageObject->removeKeyframeWithoutUndo(m_frame);
Toshihiro Shimizu 890ddd
			if (m_keyframes[i].second.m_isKeyframe)
Toshihiro Shimizu 890ddd
				stageObject->setKeyframeWithoutUndo(m_frame, m_keyframes[i].second);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		notify();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TXsheet *xsh = getXsheet();
Toshihiro Shimizu 890ddd
		for (int i = 0; i < (int)m_keyframes.size(); i++) {
Toshihiro Shimizu 890ddd
			TStageObject *stageObject = getXsheet()->getStageObject(m_keyframes[i].first);
Toshihiro Shimizu 890ddd
			if (stageObject)
Toshihiro Shimizu 890ddd
				stageObject->setKeyframeWithoutUndo(m_frame);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		m_tool->setTemporaryPinnedColumns(m_newTemp);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_oldColumnIndex >= 0)
Toshihiro Shimizu 890ddd
			getRangeSet(m_oldColumnIndex)->removeRange(m_oldRange.first, m_oldRange.second);
Toshihiro Shimizu 890ddd
		if (m_columnIndex >= 0) {
Toshihiro Shimizu 890ddd
			TPinnedRangeSet *rangeSet = getRangeSet(m_columnIndex);
Toshihiro Shimizu 890ddd
			rangeSet->setRange(m_newRange.first, m_newRange.second);
Toshihiro Shimizu 890ddd
			rangeSet->setPlacement(m_newPlacement);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		notify();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	int getSize() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return sizeof *this;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::togglePinnedStatus(int columnIndex, int frame, bool shiftPressed)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	Skeleton skeleton;
Toshihiro Shimizu 890ddd
	buildSkeleton(skeleton, columnIndex);
Toshihiro Shimizu 890ddd
	if (!skeleton.getRootBone() || !skeleton.getRootBone()->getStageObject())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	Skeleton::Bone *bone = skeleton.getBoneByColumnIndex(columnIndex);
Toshihiro Shimizu 890ddd
	assert(bone);
Toshihiro Shimizu 890ddd
	if (!bone)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TogglePinnedStatusUndo *undo = new TogglePinnedStatusUndo(this, frame);
Toshihiro Shimizu 890ddd
	for (int i = 0; i < skeleton.getBoneCount(); i++) {
Toshihiro Shimizu 890ddd
		TStageObject *obj = skeleton.getBone(i)->getStageObject();
Toshihiro Shimizu 890ddd
		if (obj) {
Toshihiro Shimizu 890ddd
			undo->addBoneId(obj->getId());
Toshihiro Shimizu 890ddd
			obj->setKeyframeWithoutUndo(frame);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
	getApplication()->getCurrentObject()->notifyObjectIdChanged(false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	undo->setOldTemp(m_temporaryPinnedColumns);
Toshihiro Shimizu 890ddd
	bool isTemporaryPinned = m_temporaryPinnedColumns.count(columnIndex) > 0;
Toshihiro Shimizu 890ddd
	if (shiftPressed || isTemporaryPinned) {
Toshihiro Shimizu 890ddd
		if (isTemporaryPinned)
Toshihiro Shimizu 890ddd
			m_temporaryPinnedColumns.erase(columnIndex);
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			m_temporaryPinnedColumns.insert(columnIndex);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		TXsheet *xsh = TTool::getApplication()->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
		TAffine placement = xsh->getPlacement(bone->getStageObject()->getId(), frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TStageObjectId rootId = skeleton.getRootBone()->getStageObject()->getId();
Toshihiro Shimizu 890ddd
		TAffine rootPlacement = xsh->getPlacement(rootId, frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int pinnedStatus = bone->getPinnedStatus();
Toshihiro Shimizu 890ddd
		if (pinnedStatus != Skeleton::Bone::PINNED) {
Toshihiro Shimizu 890ddd
			int oldPinned = -1;
Toshihiro Shimizu 890ddd
			for (int i = 0; i < skeleton.getBoneCount(); i++) {
Toshihiro Shimizu 890ddd
				TStageObject *obj = skeleton.getBone(i)->getStageObject();
Toshihiro Shimizu 890ddd
				if (obj->getPinnedRangeSet()->isPinned(frame)) {
Toshihiro Shimizu 890ddd
					oldPinned = i;
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			int lastFrame = 1000000;
Toshihiro Shimizu 890ddd
			if (oldPinned >= 0) {
Toshihiro Shimizu 890ddd
				assert(skeleton.getBone(oldPinned) != bone);
Toshihiro Shimizu 890ddd
				TStageObject *obj = skeleton.getBone(oldPinned)->getStageObject();
Toshihiro Shimizu 890ddd
				const TPinnedRangeSet::Range *range = obj->getPinnedRangeSet()->getRange(frame);
Toshihiro Shimizu 890ddd
				assert(range && range->first <= frame && frame <= range->second);
Toshihiro Shimizu 890ddd
				lastFrame = range->second;
Toshihiro Shimizu 890ddd
				TPinnedRangeSet *rangeSet = obj->getPinnedRangeSet();
Toshihiro Shimizu 890ddd
				rangeSet->removeRange(frame, range->second);
Toshihiro Shimizu 890ddd
				obj->invalidate();
Toshihiro Shimizu 890ddd
				undo->setOldRange(oldPinned, frame, range->second, rangeSet->getPlacement());
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				for (int i = 0; i < skeleton.getBoneCount(); i++) {
Toshihiro Shimizu 890ddd
					TStageObject *obj = skeleton.getBone(i)->getStageObject();
Toshihiro Shimizu 890ddd
					const TPinnedRangeSet::Range *range = obj->getPinnedRangeSet()->getNextRange(frame);
Toshihiro Shimizu 890ddd
					if (range) {
Toshihiro Shimizu 890ddd
						assert(range->first > frame);
Toshihiro Shimizu 890ddd
						if (range->first - 1 < lastFrame)
Toshihiro Shimizu 890ddd
							lastFrame = range->first - 1;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TStageObject *obj = bone->getStageObject();
Toshihiro Shimizu 890ddd
			TPinnedRangeSet *rangeSet = obj->getPinnedRangeSet();
Toshihiro Shimizu 890ddd
			rangeSet->setRange(frame, lastFrame);
Toshihiro Shimizu 890ddd
			if (frame == 0) {
Toshihiro Shimizu 890ddd
				// this code should be moved elsewhere, possibly in the stageobject implementation
Toshihiro Shimizu 890ddd
				// the idea is to remove the normal
Toshihiro Shimizu 890ddd
				TStageObject *rootObj = skeleton.getRootBone()->getStageObject();
Toshihiro Shimizu 890ddd
				rootObj->setStatus(TStageObject::XY);
Toshihiro Shimizu 890ddd
				placement = rootObj->getPlacement(0).inv() * placement;
Toshihiro Shimizu 890ddd
				rootObj->setStatus(TStageObject::IK);
Toshihiro Shimizu 890ddd
				rangeSet->setPlacement(placement);
Toshihiro Shimizu 890ddd
				rootObj->invalidate();
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			undo->setNewRange(bone->getColumnIndex(), frame, lastFrame, rangeSet->getPlacement());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	undo->setNewTemp(m_temporaryPinnedColumns);
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::drawSkeleton(const Skeleton &skeleton, int row)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	bool buildingSkeleton = m_mode.getValue() == BUILD_SKELETON;
Toshihiro Shimizu 890ddd
	bool ikEnabled = m_mode.getValue() == INVERSE_KINEMATICS;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = getXsheet();
Toshihiro Shimizu 890ddd
	std::vector<int> showBoneIndex;</int>
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < skeleton.getBoneCount(); i++) {
Toshihiro Shimizu 890ddd
		Skeleton::Bone *bone = skeleton.getBone(i);
Toshihiro Shimizu 890ddd
		TStageObjectId id = bone->getStageObject()->getId();
Toshihiro Shimizu 890ddd
		bool canShow = canShowBone(bone, xsh, row);
Toshihiro Shimizu 890ddd
		if (!canShow)
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		showBoneIndex.push_back(i);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool changingParent = dynamic_cast<parentchangetool *="">(m_dragTool) != 0;</parentchangetool>
Toshihiro Shimizu 890ddd
	TStageObjectId currentObjectId = TTool::getApplication()->getCurrentObject()->getObjectId();
Shinya Kitaoka 3bfa54
	std::string currentHandle = xsh->getStageObject(currentObjectId)->getHandle();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)showBoneIndex.size(); i++) {
Toshihiro Shimizu 890ddd
		Skeleton::Bone *bone = skeleton.getBone(showBoneIndex[i]);
Toshihiro Shimizu 890ddd
		TStageObjectId id = bone->getStageObject()->getId();
Toshihiro Shimizu 890ddd
		bool isCurrent = id == currentObjectId;
Toshihiro Shimizu 890ddd
		if (isCurrent && buildingSkeleton && m_parentProbeEnabled) {
Toshihiro Shimizu 890ddd
			if (!m_magicLinks.empty()) {
Toshihiro Shimizu 890ddd
				drawBone(bone->getCenter(), m_magicLinks[0].m_h1.m_pos, false);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			drawBone(bone->getCenter(), m_parentProbe, true);
Toshihiro Shimizu 890ddd
		} else if (ikEnabled) {
Toshihiro Shimizu 890ddd
			if (bone->getParent())
Toshihiro Shimizu 890ddd
				drawIKBone(bone->getCenter(), bone->getParent()->getCenter());
Toshihiro Shimizu 890ddd
		} else if (bone->getParent() || isCurrent) {
Toshihiro Shimizu 890ddd
			double pixelSize = getPixelSize();
Toshihiro Shimizu 890ddd
			TPointD a = bone->getCenter();
Toshihiro Shimizu 890ddd
			TPointD b, pm;
Toshihiro Shimizu 890ddd
			if (bone->getParent()) {
Toshihiro Shimizu 890ddd
				b = bone->getParent()->getCenter();
Toshihiro Shimizu 890ddd
				pm = (a + b) * 0.5;
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				pm = b = a + TPointD(0, 60) * pixelSize;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			bool boneIsVisible = false;
Toshihiro Shimizu 890ddd
			if (buildingSkeleton) {
Toshihiro Shimizu 890ddd
				boneIsVisible = true;
Toshihiro Shimizu 890ddd
				if (bone->isSelected())
Toshihiro Shimizu 890ddd
					drawBone(a, b, true);
Toshihiro Shimizu 890ddd
				else if (!m_showOnlyActiveSkeleton.getValue())
Toshihiro Shimizu 890ddd
					drawBone(a, b, false);
Toshihiro Shimizu 890ddd
				else
Toshihiro Shimizu 890ddd
					boneIsVisible = false;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			if (boneIsVisible && isCurrent) {
Toshihiro Shimizu 890ddd
				// draw change parent gadget
Toshihiro Shimizu 890ddd
				double r = pixelSize * 5;
Toshihiro Shimizu 890ddd
				if (isPicking()) {
Toshihiro Shimizu 890ddd
					// int code = TD_ResetParent + bone->getStageObject()->getId().getIndex();
Toshihiro Shimizu 890ddd
					glPushName(TD_ChangeParent);
Toshihiro Shimizu 890ddd
					tglDrawDisk(pm, r);
Toshihiro Shimizu 890ddd
					glPopName();
Toshihiro Shimizu 890ddd
				} else {
Toshihiro Shimizu 890ddd
					if (m_device == TD_ChangeParent) {
Toshihiro Shimizu 890ddd
						glColor4d(0.47 * alpha, 0.6 * alpha, 0.65 * alpha, alpha);
Toshihiro Shimizu 890ddd
						r *= 1.5;
Toshihiro Shimizu 890ddd
					} else
Toshihiro Shimizu 890ddd
						glColor4d(0.37 * alpha, 0.5 * alpha, 0.55 * alpha, alpha);
Toshihiro Shimizu 890ddd
					glRectd(pm.x - r, pm.y - r, pm.x + r, pm.y + r);
Toshihiro Shimizu 890ddd
					glColor3d(0, 0, 0);
Toshihiro Shimizu 890ddd
					tglDrawRect(pm.x - r, pm.y - r, pm.x + r, pm.y + r);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)showBoneIndex.size(); i++) {
Toshihiro Shimizu 890ddd
		Skeleton::Bone *bone = skeleton.getBone(showBoneIndex[i]);
Toshihiro Shimizu 890ddd
		if (!m_showOnlyActiveSkeleton.getValue() || bone->isSelected())
Toshihiro Shimizu 890ddd
			drawJoint(bone->getCenter(),
Toshihiro Shimizu 890ddd
					  currentObjectId == bone->getStageObject()->getId() &&
Toshihiro Shimizu 890ddd
						  currentHandle.find("H") != 0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::getImageBoundingBox(TRectD &bbox, TAffine &aff, int frame, int columnIndex)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TAffine columnAff = getXsheet()->getPlacement(TStageObjectId::ColumnId(columnIndex), frame);
Toshihiro Shimizu 890ddd
	// TAffine affine = getColumnMatrix(columnIndex);
Toshihiro Shimizu 890ddd
	TXshCell cell = getXsheet()->getCell(frame, columnIndex);
Toshihiro Shimizu 890ddd
	TImageP image = cell.getImage(false);
Toshihiro Shimizu 890ddd
	TToonzImageP ti = image;
Toshihiro Shimizu 890ddd
	TVectorImageP vi = image;
Toshihiro Shimizu 890ddd
	if (ti) {
Toshihiro Shimizu 890ddd
		TAffine imageDpiAff;
Toshihiro Shimizu 890ddd
		if (cell.m_level->getSimpleLevel())
Toshihiro Shimizu 890ddd
			imageDpiAff = getDpiAffine(cell.m_level->getSimpleLevel(), cell.m_frameId, true);
Toshihiro Shimizu 890ddd
		aff = columnAff * imageDpiAff;
Toshihiro Shimizu 890ddd
		bbox = ToonzImageUtils::convertRasterToWorld(convert(ti->getBBox()), ti) * ti->getSubsampling();
Toshihiro Shimizu 890ddd
		ToolUtils::drawRect(bbox * ti->getSubsampling(), TPixel32(200, 200, 200), 0x5555);
Toshihiro Shimizu 890ddd
	} else if (vi) {
Toshihiro Shimizu 890ddd
		bbox = vi->getBBox();
Toshihiro Shimizu 890ddd
		aff = columnAff;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		bbox = TRectD();
Toshihiro Shimizu 890ddd
		aff = TAffine();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::drawLevelBoundingBox(int frame, int columnIndex)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TAffine affine = getCurrentColumnMatrix();
Toshihiro Shimizu 890ddd
	TXshCell cell = getXsheet()->getCell(frame, columnIndex);
Toshihiro Shimizu 890ddd
	TImageP image = cell.getImage(false);
Toshihiro Shimizu 890ddd
	TToonzImageP ti = image;
Toshihiro Shimizu 890ddd
	TVectorImageP vi = image;
Toshihiro Shimizu 890ddd
	glPushMatrix();
Toshihiro Shimizu 890ddd
	if (affine != getMatrix())
Toshihiro Shimizu 890ddd
		tglMultMatrix(getMatrix().inv() * affine);
Toshihiro Shimizu 890ddd
	if (ti) {
Toshihiro Shimizu 890ddd
		TPointD dpiScale = getViewer()->getDpiScale();
Toshihiro Shimizu 890ddd
		glScaled(dpiScale.x, dpiScale.y, 1);
Toshihiro Shimizu 890ddd
		TRectD bbox = ToonzImageUtils::convertRasterToWorld(convert(ti->getBBox()), ti);
Toshihiro Shimizu 890ddd
		ToolUtils::drawRect(bbox * ti->getSubsampling(), TPixel32(200, 200, 200), 0x5555);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (vi) {
Toshihiro Shimizu 890ddd
		TRectD bbox = vi->getBBox();
Toshihiro Shimizu 890ddd
		ToolUtils::drawRect(bbox, TPixel32(200, 200, 200), 0x5555);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	glPopMatrix();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::drawIKJoint(const Skeleton::Bone *bone)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPointD pos = bone->getCenter();
Toshihiro Shimizu 890ddd
	const double r0 = 6 * getPixelSize(), r1 = r0 / 3;
Toshihiro Shimizu 890ddd
	int code = TD_LockStageObject + bone->getColumnIndex();
Toshihiro Shimizu 890ddd
	glPushName(code);
Toshihiro Shimizu 890ddd
	glColor3d(0.8, 0.5, 0.05);
Toshihiro Shimizu 890ddd
	if (bone->getPinnedStatus() != Skeleton::Bone::FREE) {
Toshihiro Shimizu 890ddd
		if (bone->getPinnedStatus() == Skeleton::Bone::TEMP_PINNED) {
Toshihiro Shimizu 890ddd
			double r1 = r0 * 0.60;
Toshihiro Shimizu 890ddd
			glColor3d(60.0 / 255.0, 250.0 / 255.0, 1.0);
Toshihiro Shimizu 890ddd
			glRectd(pos.x - r0, pos.y - r0, pos.x + r0, pos.y + r0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			glColor3d(0.78, 0.62, 0);
Toshihiro Shimizu 890ddd
			glRectd(pos.x - r1, pos.y - r1, pos.x + r1, pos.y + r1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			glColor3d(0.2, 0.1, 0.05);
Toshihiro Shimizu 890ddd
			tglDrawRect(pos.x - r0, pos.y - r0, pos.x + r0, pos.y + r0);
Toshihiro Shimizu 890ddd
			tglDrawRect(pos.x - r1, pos.y - r1, pos.x + r1, pos.y + r1);
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			glColor3d(0, 175.0 / 255.0, 1.0);
Toshihiro Shimizu 890ddd
			glRectd(pos.x - r0, pos.y - r0, pos.x + r0, pos.y + r0);
Toshihiro Shimizu 890ddd
			glColor3d(0.2, 0.1, 0.05);
Toshihiro Shimizu 890ddd
			tglDrawRect(pos.x - r0, pos.y - r0, pos.x + r0, pos.y + r0);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		if (bone->isSelected())
Toshihiro Shimizu 890ddd
			glColor3d(1, 0.78, 0.19);
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			glColor3d(0.78, 0.62, 0);
Toshihiro Shimizu 890ddd
		tglDrawDisk(pos, r0);
Toshihiro Shimizu 890ddd
		glColor3d(0.2, 0.1, 0.05);
Toshihiro Shimizu 890ddd
		tglDrawCircle(pos, r0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_device == code) {
Toshihiro Shimizu 890ddd
		glColor3d(0.9, 0.1, 0.1);
Toshihiro Shimizu 890ddd
		tglFillRect(pos.x - r1, pos.y - r1, pos.x + r1, pos.y + r1);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		glColor3d(0.2, 0.1, 0.05);
Toshihiro Shimizu 890ddd
		const double r3 = 2 * getPixelSize();
Toshihiro Shimizu 890ddd
		tglDrawCircle(pos, r3);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	glPopName();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::drawJoint(const TPointD &pos, bool current)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const double alpha = 0.8, ialpha = 1 - alpha;
Toshihiro Shimizu 890ddd
	double r0 = 4 * getPixelSize();
Toshihiro Shimizu 890ddd
	if (current) {
Toshihiro Shimizu 890ddd
		glPushName(TD_Center);
Toshihiro Shimizu 890ddd
		if (m_device == TD_Center) {
Toshihiro Shimizu 890ddd
			glColor4d(0.9 * alpha, 0.8 * alpha, 0.2 * alpha, alpha);
Toshihiro Shimizu 890ddd
			r0 *= 1.5;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			glColor4d(((255.0 / 255.0) - ialpha) / alpha, ((200.0 / 255.0) - ialpha) / alpha, ((48.0 / 255.0) - ialpha) / alpha, alpha);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		tglDrawDisk(pos, r0);
Toshihiro Shimizu 890ddd
		glColor3d(0.2, 0.1, 0.05);
Toshihiro Shimizu 890ddd
		tglDrawCircle(pos, r0);
Toshihiro Shimizu 890ddd
		glPopName();
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		// in build skeleton center is clickable, but only the current one
Toshihiro Shimizu 890ddd
		if (m_mode.getValue() == BUILD_SKELETON)
Toshihiro Shimizu 890ddd
			glColor4d(0.60 * alpha, 0.60 * alpha, 0.60 * alpha, alpha);
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			glColor4d(0.78 * alpha, 0.62 * alpha, 0 * alpha, alpha);
Toshihiro Shimizu 890ddd
		tglDrawDisk(pos, r0);
Toshihiro Shimizu 890ddd
		glColor3d(0.2, 0.1, 0.05);
Toshihiro Shimizu 890ddd
		tglDrawCircle(pos, r0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::drawBone(const TPointD &a, const TPointD &b, bool selected)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const double alpha = 0.8;
Toshihiro Shimizu 890ddd
	// se sono troppo vicini niente da fare
Toshihiro Shimizu 890ddd
	TPointD delta = b - a;
Toshihiro Shimizu 890ddd
	if (norm2(delta) < 0.001)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	TPointD u = getPixelSize() * 2.5 * normalize(rotate90(delta));
Toshihiro Shimizu 890ddd
	if (selected)
Toshihiro Shimizu 890ddd
		glColor4d(0.9 * alpha, 0.9 * alpha, 0.9 * alpha, alpha);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		glColor4d(0.58 * alpha, 0.58 * alpha, 0.58 * alpha, alpha);
Toshihiro Shimizu 890ddd
	glBegin(GL_POLYGON);
Toshihiro Shimizu 890ddd
	tglVertex(a + u);
Toshihiro Shimizu 890ddd
	tglVertex(b);
Toshihiro Shimizu 890ddd
	tglVertex(a - u);
Toshihiro Shimizu 890ddd
	glEnd();
Toshihiro Shimizu 890ddd
	glColor3d(0.2, 0.3, 0.35);
Toshihiro Shimizu 890ddd
	glBegin(GL_LINE_STRIP);
Toshihiro Shimizu 890ddd
	tglVertex(a + u);
Toshihiro Shimizu 890ddd
	tglVertex(b);
Toshihiro Shimizu 890ddd
	tglVertex(a - u);
Toshihiro Shimizu 890ddd
	glEnd();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::drawIKBone(const TPointD &a, const TPointD &b)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// se sono troppo vicini niente da fare
Toshihiro Shimizu 890ddd
	TPointD delta = b - a;
Toshihiro Shimizu 890ddd
	if (norm2(delta) < 0.001)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	TPointD u = getPixelSize() * 2.5 * normalize(rotate90(delta));
Toshihiro Shimizu 890ddd
	glColor3d(0.58, 0.58, 0.58);
Toshihiro Shimizu 890ddd
	glBegin(GL_POLYGON);
Toshihiro Shimizu 890ddd
	tglVertex(a + u);
Toshihiro Shimizu 890ddd
	tglVertex(b + u);
Toshihiro Shimizu 890ddd
	tglVertex(b - u);
Toshihiro Shimizu 890ddd
	tglVertex(a - u);
Toshihiro Shimizu 890ddd
	glEnd();
Toshihiro Shimizu 890ddd
	glColor3d(0.2, 0.3, 0.35);
Toshihiro Shimizu 890ddd
	glBegin(GL_LINES);
Toshihiro Shimizu 890ddd
	tglVertex(a + u);
Toshihiro Shimizu 890ddd
	tglVertex(b + u);
Toshihiro Shimizu 890ddd
	tglVertex(a - u);
Toshihiro Shimizu 890ddd
	tglVertex(b - u);
Toshihiro Shimizu 890ddd
	glEnd();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::computeMagicLinks()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//TODO: spostare qui il calcolo dei magic link
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::drawHooks()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// camera stand reference system
Toshihiro Shimizu 890ddd
	//glColor3d(0,0,1);
Toshihiro Shimizu 890ddd
	//tglDrawRect(3,3,97,97);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//glColor3d(0,1,1);
Toshihiro Shimizu 890ddd
	//tglDrawRect(0,100,Stage::inch,110);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QTime time;
Toshihiro Shimizu 890ddd
	time.start();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_magicLinks.clear();
Toshihiro Shimizu 890ddd
	computeMagicLinks();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTool::Application *app = TTool::getApplication();
Toshihiro Shimizu 890ddd
	TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
	int row = app->getCurrentFrame()->getFrame();
Toshihiro Shimizu 890ddd
	int col = app->getCurrentColumn()->getColumnIndex();
Toshihiro Shimizu 890ddd
	TPointD dpiScale = getViewer()->getDpiScale();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// glColor3d(1,0,1);
Toshihiro Shimizu 890ddd
	// tglDrawRect(-100*dpiScale.x, -100*dpiScale.y, 0,0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// I should not show hooks of columns already connected with the current one
Toshihiro Shimizu 890ddd
	// ("linking" to those hooks would create evil loops in the hierarchy)
Toshihiro Shimizu 890ddd
	std::set<int> connectedColumns;</int>
Toshihiro Shimizu 890ddd
	getConnectedColumns(connectedColumns, xsh, col);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<hookdata> currentColumnHooks;</hookdata>
Toshihiro Shimizu 890ddd
	std::vector<hookdata> otherColumnsHooks;</hookdata>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// fill currentColumnHooks
Toshihiro Shimizu 890ddd
	// detect otherColumn (i.e. the active column during a click&drag operator
Toshihiro Shimizu 890ddd
	int otherColumn = -1;
Toshihiro Shimizu 890ddd
	if (m_parentProbeEnabled) {
Toshihiro Shimizu 890ddd
		// qDebug("  parent probe enabled");
Toshihiro Shimizu 890ddd
		// currentColumnHooks <- current column & current handle
Toshihiro Shimizu 890ddd
		int hookId = 0;
Toshihiro Shimizu 890ddd
		std::string handle = xsh->getStageObject(TStageObjectId::ColumnId(col))->getHandle();
Toshihiro Shimizu 890ddd
		if (handle.find("H") == 0) {
Toshihiro Shimizu 890ddd
			int j = 1;
Toshihiro Shimizu 890ddd
			while (j < (int)handle.size() && '0' <= handle[j] && handle[j] <= '9') {
Toshihiro Shimizu 890ddd
				hookId = hookId * 10 + (int)handle[j] - '0';
Toshihiro Shimizu 890ddd
				j++;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		currentColumnHooks.push_back(HookData(xsh, col, hookId, m_parentProbe));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// otherColumn = "picked" column not connected
Toshihiro Shimizu 890ddd
		TPoint parentProbePos = getViewer()->worldToPos(m_parentProbe);
Toshihiro Shimizu 890ddd
		std::vector<int> indexes;</int>
Toshihiro Shimizu 890ddd
		getViewer()->posToColumnIndexes(parentProbePos, indexes, getPixelSize() * 10, false);
Toshihiro Shimizu 890ddd
		for (int i = (int)indexes.size() - 1; i >= 0; i--) {
Toshihiro Shimizu 890ddd
			if (connectedColumns.count(indexes[i]) == 0) {
Toshihiro Shimizu 890ddd
				otherColumn = indexes[i];
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		// if the mouse is not on a stroke, I'm using the "old" m_otherColumn, if any.
Toshihiro Shimizu 890ddd
		// (this is needed because of the hooks put inside of unfilled regions)
Toshihiro Shimizu 890ddd
		if (otherColumn < 0 && m_otherColumn >= 0) {
Toshihiro Shimizu 890ddd
			if (m_otherColumnBBox.contains(m_otherColumnBBoxAff.inv() * m_parentProbe))
Toshihiro Shimizu 890ddd
				otherColumn = m_otherColumn;
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				m_otherColumn = -1;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		// parent probe not enabled: get all hooks of current column. other column = -1
Toshihiro Shimizu 890ddd
		getHooks(currentColumnHooks, xsh, row, col, TPointD(1, 1)); // dpiScale);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// other columns hooks <- all hooks of all unlinked columns
Toshihiro Shimizu 890ddd
	for (int i = 0; i < xsh->getColumnCount(); i++)
Toshihiro Shimizu 890ddd
		if (xsh->getColumn(i)->isCamstandVisible())
Toshihiro Shimizu 890ddd
			if (connectedColumns.count(i) == 0)
Toshihiro Shimizu 890ddd
				getHooks(otherColumnsHooks, xsh, row, i, TPointD(1, 1)); // dpiScale);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
  qDebug("  time=%dms", time.elapsed());
Toshihiro Shimizu 890ddd
  qDebug("  %d hooks (current column)", currentColumnHooks.size());
Toshihiro Shimizu 890ddd
  for(int i=0;i<(int)currentColumnHooks.size();i++)
Toshihiro Shimizu 890ddd
    qDebug("    %d,%d",currentColumnHooks[i].m_columnIndex,currentColumnHooks[i].m_hookId);
Toshihiro Shimizu 890ddd
  qDebug("  %d hooks (other columns)", otherColumnsHooks.size());
Toshihiro Shimizu 890ddd
  for(int i=0;i<(int)otherColumnsHooks.size();i++)
Toshihiro Shimizu 890ddd
    qDebug("    %d,%d",otherColumnsHooks[i].m_columnIndex,otherColumnsHooks[i].m_hookId);
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<trectd> balloons;</trectd>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// draw current column hooks
Toshihiro Shimizu 890ddd
	for (int i = 0; i < (int)currentColumnHooks.size(); i++) {
Toshihiro Shimizu 890ddd
		const HookData &hook = currentColumnHooks[i];
Toshihiro Shimizu 890ddd
		if (hook.m_name == "")
Toshihiro Shimizu 890ddd
			continue; // should not happen
Toshihiro Shimizu 890ddd
		int code = TD_Hook + hook.m_hookId;
Toshihiro Shimizu 890ddd
		TPointD pos = hook.m_pos;
Toshihiro Shimizu 890ddd
		ToolUtils::drawHook(pos, ToolUtils::OtherLevelHook);
Toshihiro Shimizu 890ddd
		glPushName(code);
Toshihiro Shimizu 890ddd
		TPixel32 color(200, 220, 205, 200);
Toshihiro Shimizu 890ddd
		if (hook.m_isPivot)
Toshihiro Shimizu 890ddd
			color = TPixel32(200, 200, 10, 200);
Toshihiro Shimizu 890ddd
		else if (code == m_device)
Toshihiro Shimizu 890ddd
			color = TPixel32(185, 255, 255);
Toshihiro Shimizu 890ddd
		ToolUtils::drawBalloon(pos, hook.m_name, color, TPoint(20, 20), isPicking(), &balloons);
Toshihiro Shimizu 890ddd
		glPopName();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_parentProbeEnabled) {
Toshihiro Shimizu 890ddd
		for (int i = 0; i < (int)otherColumnsHooks.size(); i++)
Toshihiro Shimizu 890ddd
			ToolUtils::drawHook(otherColumnsHooks[i].m_pos, ToolUtils::OtherLevelHook);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// search for magic links
Toshihiro Shimizu 890ddd
	double minDist2 = 0;
Toshihiro Shimizu 890ddd
	double snapRadius2 = 100 * getPixelSize() * getPixelSize();
Toshihiro Shimizu 890ddd
	double snapRadius2bis = 100;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_parentProbeEnabled) {
Toshihiro Shimizu 890ddd
		// "static" magic links: no parent probe
Toshihiro Shimizu 890ddd
		for (int i = 0; i < (int)currentColumnHooks.size(); i++) {
Toshihiro Shimizu 890ddd
			for (int j = 0; j < (int)otherColumnsHooks.size(); j++) {
Toshihiro Shimizu 890ddd
				double dist2 = norm2(currentColumnHooks[i].m_pos - otherColumnsHooks[j].m_pos);
Toshihiro Shimizu 890ddd
				if (currentColumnHooks[i].m_hookId == 0 || otherColumnsHooks[j].m_hookId == 0)
Toshihiro Shimizu 890ddd
					continue;
Toshihiro Shimizu 890ddd
				if (dist2 < snapRadius2bis) {
Toshihiro Shimizu 890ddd
					m_magicLinks.push_back(MagicLink(currentColumnHooks[i], otherColumnsHooks[j], dist2));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					qDebug("  magic link_a %d (%d,%d) %d (%d,%d); dist=%f",
Toshihiro Shimizu 890ddd
						   i,
Toshihiro Shimizu 890ddd
						   currentColumnHooks[i].m_columnIndex,
Toshihiro Shimizu 890ddd
						   currentColumnHooks[i].m_hookId,
Toshihiro Shimizu 890ddd
						   j,
Toshihiro Shimizu 890ddd
						   otherColumnsHooks[j].m_columnIndex,
Toshihiro Shimizu 890ddd
						   otherColumnsHooks[j].m_hookId,
Toshihiro Shimizu 890ddd
						   dist2);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_parentProbeEnabled) {
Toshihiro Shimizu 890ddd
		// search for the closest hook of the picked column
Toshihiro Shimizu 890ddd
		int i = -1, j = -1;
Toshihiro Shimizu 890ddd
		double minDist2 = snapRadius2;
Toshihiro Shimizu 890ddd
		for (i = 0; i < (int)otherColumnsHooks.size(); i++) {
Toshihiro Shimizu 890ddd
			double dist2 = tdistance2(otherColumnsHooks[i].m_pos, m_parentProbe);
Toshihiro Shimizu 890ddd
			if (dist2 < minDist2) {
Toshihiro Shimizu 890ddd
				j = i;
Toshihiro Shimizu 890ddd
				minDist2 = dist2;
Toshihiro Shimizu 890ddd
				otherColumn = otherColumnsHooks[i].m_columnIndex;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_parentProbeEnabled && otherColumn >= 0) //  && m_magicLinks.empty()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		// "dynamic" magic links: probing and picking a column
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// show image bounding box
Toshihiro Shimizu 890ddd
		m_otherColumn = otherColumn;
Toshihiro Shimizu 890ddd
		getImageBoundingBox(m_otherColumnBBox, m_otherColumnBBoxAff, row, otherColumn);
Toshihiro Shimizu 890ddd
		if (!m_otherColumnBBox.isEmpty()) {
Toshihiro Shimizu 890ddd
			glPushMatrix();
Toshihiro Shimizu 890ddd
			tglMultMatrix(m_otherColumnBBoxAff);
Toshihiro Shimizu 890ddd
			ToolUtils::drawRect(m_otherColumnBBox, TPixel32(188, 202, 191), 0xF0F0);
Toshihiro Shimizu 890ddd
			//tglDrawRect(img->getBBox());
Toshihiro Shimizu 890ddd
			glPopMatrix();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		/*
Toshihiro Shimizu 890ddd
    TXshCell cell = xsh->getCell(row, otherColumn);
Toshihiro Shimizu 890ddd
    //TAffine aff = xsh->getPlacement(TStageObjectId::ColumnId(otherColumn),row);
Toshihiro Shimizu 890ddd
    //m_otherColumnAff = aff;
Toshihiro Shimizu 890ddd
    TImageP img = cell.getImage(false);
Toshihiro Shimizu 890ddd
    if(img)
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
      getImageBoundingBox(m_otherColumnBBox, m_otherColumnBBoxAff, row, otherColumn);
Toshihiro Shimizu 890ddd
      //glColor3d(188.0/255.0, 202.0/255.0, 191.0/255.0);
Toshihiro Shimizu 890ddd
      glPushMatrix();
Toshihiro Shimizu 890ddd
      tglMultMatrix(aff * imageDpiAff);
Toshihiro Shimizu 890ddd
      ToolUtils::drawRect(img->getBBox(), TPixel32(188,202,191), 0xF0F0);
Toshihiro Shimizu 890ddd
      //tglDrawRect(img->getBBox());
Toshihiro Shimizu 890ddd
      glPopMatrix();
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
		// search for the closest hook of the picked column
Toshihiro Shimizu 890ddd
		int i = -1, j = -1;
Toshihiro Shimizu 890ddd
		double minDist2 = snapRadius2;
Toshihiro Shimizu 890ddd
		for (i = 0; i < (int)otherColumnsHooks.size(); i++)
Toshihiro Shimizu 890ddd
			if (otherColumnsHooks[i].m_columnIndex == otherColumn) {
Toshihiro Shimizu 890ddd
				double dist2 = tdistance2(otherColumnsHooks[i].m_pos, m_parentProbe);
Toshihiro Shimizu 890ddd
				if (j < 0)
Toshihiro Shimizu 890ddd
					j = i;
Toshihiro Shimizu 890ddd
				else if (dist2 < minDist2 || otherColumnsHooks[i].m_hookId == 0) {
Toshihiro Shimizu 890ddd
					j = i;
Toshihiro Shimizu 890ddd
					minDist2 = dist2;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		// visualize a balloon for the closest hook
Toshihiro Shimizu 890ddd
		if (0 <= j && j < (int)otherColumnsHooks.size()) {
Toshihiro Shimizu 890ddd
			// I want to get a specific color when overlaying the label on white
Toshihiro Shimizu 890ddd
			int alfa = 100, ialfa = 255 - alfa;
Toshihiro Shimizu 890ddd
			TPixel32 color(255 * (188 - ialfa) / alfa, 255 * (202 - ialfa) / alfa, 255 * (191 - ialfa) / alfa, alfa);
Toshihiro Shimizu 890ddd
			ToolUtils::drawBalloon(
Toshihiro Shimizu 890ddd
				otherColumnsHooks[j].m_pos,
Toshihiro Shimizu 890ddd
				otherColumnsHooks[j].m_name, // getHandle(),
Toshihiro Shimizu 890ddd
				color,
Toshihiro Shimizu 890ddd
				TPoint(20, 20),
Toshihiro Shimizu 890ddd
				false,
Toshihiro Shimizu 890ddd
				&balloons);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			HookData baseHook = currentColumnHooks[0];
Toshihiro Shimizu 890ddd
			baseHook.m_pos = otherColumnsHooks[j].m_pos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// this is also a magic link
Toshihiro Shimizu 890ddd
			m_magicLinks.push_back(MagicLink(baseHook, otherColumnsHooks[j], 10000));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// visualize all the magic links
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int i = 0; i < (int)m_magicLinks.size(); i++) {
Toshihiro Shimizu 890ddd
		const MagicLink &magicLink = m_magicLinks[i];
Toshihiro Shimizu 890ddd
		const HookData &h1 = magicLink.m_h1;
Toshihiro Shimizu 890ddd
		std::string name;
Toshihiro Shimizu 890ddd
		name = (m_parentProbeEnabled ? "Linking " : "Link ") + removeTrailingH(magicLink.m_h0.getHandle()) +
Toshihiro Shimizu 890ddd
			   " to Col " + toString(h1.m_columnIndex + 1) + "/" + removeTrailingH(h1.getHandle());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int code = TD_MagicLink + i;
Toshihiro Shimizu 890ddd
		glPushName(code);
Toshihiro Shimizu 890ddd
		TPixel32 color(100, 255, 100, 100);
Toshihiro Shimizu 890ddd
		if (code == m_device)
Toshihiro Shimizu 890ddd
			color = TPixel32(185, 255, 255);
Toshihiro Shimizu 890ddd
		ToolUtils::drawBalloon(magicLink.m_h0.m_pos, name, color, TPoint(20, -20), isPicking(), &balloons);
Toshihiro Shimizu 890ddd
		glPopName();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::drawDrawingBrowser(const TXshCell &cell, const TPointD ¢er)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!cell.m_level || cell.m_level->getFrameCount() <= 1)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	double pixelSize = getPixelSize();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::string name = toString(cell.m_level->getName()) + "." + toString(cell.m_frameId.getNumber());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString qText = QString::fromStdString(name);
Toshihiro Shimizu 890ddd
	QFont font("Arial", 10); // ,QFont::Bold);
Toshihiro Shimizu 890ddd
	QFontMetrics fm(font);
Toshihiro Shimizu 890ddd
	QSize textSize = fm.boundingRect(qText).size();
Toshihiro Shimizu 890ddd
	int arrowHeight = 10;
Toshihiro Shimizu 890ddd
	int minTextWidth = 2 * arrowHeight + 5;
Toshihiro Shimizu 890ddd
	if (textSize.width() < minTextWidth)
Toshihiro Shimizu 890ddd
		textSize.setWidth(minTextWidth);
Toshihiro Shimizu 890ddd
	QSize totalSize(textSize.width(), textSize.height() + 2 * arrowHeight);
Toshihiro Shimizu 890ddd
	TPointD p = center + TPointD(30, -arrowHeight) * pixelSize;
Toshihiro Shimizu 890ddd
	QRect textRect(0, arrowHeight, textSize.width(), textSize.height());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(glGetError() == 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isPicking()) {
Toshihiro Shimizu 890ddd
		double x0 = p.x, x1 = p.x + totalSize.width() * pixelSize;
Toshihiro Shimizu 890ddd
		double y0 = p.y, y3 = p.y + totalSize.height() * pixelSize;
Toshihiro Shimizu 890ddd
		double y1 = y0 + arrowHeight * pixelSize;
Toshihiro Shimizu 890ddd
		double y2 = y3 - arrowHeight * pixelSize;
Toshihiro Shimizu 890ddd
		double x = (x0 + x1) * 0.5;
Toshihiro Shimizu 890ddd
		double d = arrowHeight * pixelSize;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glColor3d(0, 1, 0);
Toshihiro Shimizu 890ddd
		glPushName(TD_ChangeDrawing);
Toshihiro Shimizu 890ddd
		glRectd(x0, y1, x1, y2);
Toshihiro Shimizu 890ddd
		glPopName();
Toshihiro Shimizu 890ddd
		glPushName(TD_IncrementDrawing);
Toshihiro Shimizu 890ddd
		glBegin(GL_POLYGON);
Toshihiro Shimizu 890ddd
		glVertex2d(x, y0);
Toshihiro Shimizu 890ddd
		glVertex2d(x + d, y0 + d);
Toshihiro Shimizu 890ddd
		glVertex2d(x - d, y0 + d);
Toshihiro Shimizu 890ddd
		glEnd();
Toshihiro Shimizu 890ddd
		glPopName();
Toshihiro Shimizu 890ddd
		glPushName(TD_DecrementDrawing);
Toshihiro Shimizu 890ddd
		glBegin(GL_POLYGON);
Toshihiro Shimizu 890ddd
		glVertex2d(x, y3);
Toshihiro Shimizu 890ddd
		glVertex2d(x + d, y3 - d);
Toshihiro Shimizu 890ddd
		glVertex2d(x - d, y3 - d);
Toshihiro Shimizu 890ddd
		glEnd();
Toshihiro Shimizu 890ddd
		glPopName();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(glGetError() == 0);
Toshihiro Shimizu 890ddd
		bool active = m_device == TD_ChangeDrawing || m_device == TD_IncrementDrawing || m_device == TD_DecrementDrawing;
Toshihiro Shimizu 890ddd
		QImage img(totalSize.width(), totalSize.height(), QImage::Format_ARGB32);
Toshihiro Shimizu 890ddd
		img.fill(Qt::transparent);
Toshihiro Shimizu 890ddd
		QPainter imgPainter(&img);
Toshihiro Shimizu 890ddd
		imgPainter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//imgPainter.setPen(Qt::black);
Toshihiro Shimizu 890ddd
		//imgPainter.drawRect(0,0,totalSize.width(),totalSize.height());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		imgPainter.setPen(Qt::NoPen);
Toshihiro Shimizu 890ddd
		imgPainter.setBrush(QColor(200, 200, 200, 200));
Toshihiro Shimizu 890ddd
		imgPainter.drawRect(textRect);
Toshihiro Shimizu 890ddd
		imgPainter.setPen(active ? Qt::red : Qt::black);
Toshihiro Shimizu 890ddd
		imgPainter.setBrush(Qt::NoBrush);
Toshihiro Shimizu 890ddd
		imgPainter.setFont(font);
Toshihiro Shimizu 890ddd
		imgPainter.drawText(textRect, Qt::AlignCenter, qText);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (active) {
Toshihiro Shimizu 890ddd
			int x = textRect.center().x();
Toshihiro Shimizu 890ddd
			int d = arrowHeight - 4;
Toshihiro Shimizu 890ddd
			int y = 0;
Toshihiro Shimizu 890ddd
			QPainterPath upArrow;
Toshihiro Shimizu 890ddd
			upArrow.moveTo(x, y);
Toshihiro Shimizu 890ddd
			upArrow.lineTo(x + d, y + d);
Toshihiro Shimizu 890ddd
			upArrow.lineTo(x - d, y + d);
Toshihiro Shimizu 890ddd
			upArrow.lineTo(x, y);
Toshihiro Shimizu 890ddd
			y = totalSize.height() - 1;
Toshihiro Shimizu 890ddd
			QPainterPath dnArrow;
Toshihiro Shimizu 890ddd
			dnArrow.moveTo(x, y);
Toshihiro Shimizu 890ddd
			dnArrow.lineTo(x + d, y - d);
Toshihiro Shimizu 890ddd
			dnArrow.lineTo(x - d, y - d);
Toshihiro Shimizu 890ddd
			dnArrow.lineTo(x, y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			imgPainter.setPen(Qt::NoPen);
Toshihiro Shimizu 890ddd
			imgPainter.setBrush(m_device == TD_DecrementDrawing ? QColor(255, 0, 0) : QColor(200, 100, 100));
Toshihiro Shimizu 890ddd
			imgPainter.drawPath(upArrow);
Toshihiro Shimizu 890ddd
			imgPainter.setBrush(m_device == TD_IncrementDrawing ? QColor(255, 0, 0) : QColor(200, 100, 100));
Toshihiro Shimizu 890ddd
			imgPainter.drawPath(dnArrow);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		QImage texture = QGLWidget::convertToGLFormat(img);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glRasterPos2f(p.x, p.y);
Toshihiro Shimizu 890ddd
		// glBitmap(0,0,0,0,  0,-size.height()+(y+delta.y),  NULL); //
Toshihiro Shimizu 890ddd
		glEnable(GL_BLEND);
Toshihiro Shimizu 890ddd
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Toshihiro Shimizu 890ddd
		glDrawPixels(texture.width(), texture.height(), GL_RGBA, GL_UNSIGNED_BYTE, texture.bits());
Toshihiro Shimizu 890ddd
		glDisable(GL_BLEND);
Toshihiro Shimizu 890ddd
		glColor3d(0, 0, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(glGetError() == 0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::drawMainGadget(const TPointD ¢er)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(glGetError() == GL_NO_ERROR);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double r = 10 * getPixelSize();
Toshihiro Shimizu 890ddd
	double cx = center.x + r * 1.1;
Toshihiro Shimizu 890ddd
	double cy = center.y - r * 1.1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glColor3d(1, 0, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isPicking()) {
Toshihiro Shimizu 890ddd
		glPushName(TD_Translation);
Toshihiro Shimizu 890ddd
		tglDrawDisk(TPointD(cx, cy), getPixelSize() * 9);
Toshihiro Shimizu 890ddd
		glPopName();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QImage img(19, 19, QImage::Format_ARGB32);
Toshihiro Shimizu 890ddd
	img.fill(Qt::transparent);
Toshihiro Shimizu 890ddd
	QPainter p(&img);
Toshihiro Shimizu 890ddd
	// p.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QPainterPath pp;
Toshihiro Shimizu 890ddd
	int dx = 1, dy = 0;
Toshihiro Shimizu 890ddd
	for (int i = 0; i < 4; i++) {
Toshihiro Shimizu 890ddd
		int x = 9 + dx * 8;
Toshihiro Shimizu 890ddd
		int y = 9 + dy * 8;
Toshihiro Shimizu 890ddd
		pp.moveTo(9, 9);
Toshihiro Shimizu 890ddd
		pp.lineTo(x, y);
Toshihiro Shimizu 890ddd
		pp.lineTo(x - 2 * dx - 2 * dy, y - 2 * dy + 2 * dx);
Toshihiro Shimizu 890ddd
		pp.moveTo(x, y);
Toshihiro Shimizu 890ddd
		pp.lineTo(x - 2 * dx + 2 * dy, y - 2 * dy - 2 * dx);
Toshihiro Shimizu 890ddd
		int d = dx;
Toshihiro Shimizu 890ddd
		dx = -dy;
Toshihiro Shimizu 890ddd
		dy = d;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	p.setPen(QPen(Qt::white, 3));
Toshihiro Shimizu 890ddd
	p.drawPath(pp);
Toshihiro Shimizu 890ddd
	p.setPen(Qt::black);
Toshihiro Shimizu 890ddd
	p.drawPath(pp);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	p.setBrush(QColor(54, 213, 54));
Toshihiro Shimizu 890ddd
	p.drawRect(6, 6, 6, 6);
Toshihiro Shimizu 890ddd
	QImage texture = QGLWidget::convertToGLFormat(img);
Toshihiro Shimizu 890ddd
	// texture.save("c:\\urka.png");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glRasterPos2f(center.x + r * 1.1, center.y - r * 1.1);
Toshihiro Shimizu 890ddd
	glBitmap(0, 0, 0, 0, -9, -9, NULL);
Toshihiro Shimizu 890ddd
	glEnable(GL_BLEND);
Toshihiro Shimizu 890ddd
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Toshihiro Shimizu 890ddd
	glDrawPixels(texture.width(), texture.height(), GL_RGBA, GL_UNSIGNED_BYTE, texture.bits());
Toshihiro Shimizu 890ddd
	glDisable(GL_BLEND);
Toshihiro Shimizu 890ddd
	glColor3d(0, 0, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(glGetError() == GL_NO_ERROR);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::draw()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// parent object reference system
Toshihiro Shimizu 890ddd
	//glColor3d(1,0,0);
Toshihiro Shimizu 890ddd
	//tglDrawRect(0,0,100,100);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_label != "")
Toshihiro Shimizu 890ddd
		ToolUtils::drawBalloon(m_labelPos, m_label, TPixel32::Red, TPoint(20, -20), false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool ikEnabled = m_mode.getValue() == INVERSE_KINEMATICS;
Toshihiro Shimizu 890ddd
	assert(glGetError() == GL_NO_ERROR);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// l'xsheet, oggetto (e relativo placement), frame corrente
Toshihiro Shimizu 890ddd
	TTool::Application *app = TTool::getApplication();
Toshihiro Shimizu 890ddd
	TXsheet *xsh = getXsheet();
Toshihiro Shimizu 890ddd
	assert(xsh);
Toshihiro Shimizu 890ddd
	TStageObjectId objId = app->getCurrentObject()->getObjectId();
Toshihiro Shimizu 890ddd
	// se l'oggetto corrente non e' una colonna non disegno nulla
Toshihiro Shimizu 890ddd
	if (!objId.isColumn())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TStageObject *pegbar = xsh->getStageObject(objId);
Toshihiro Shimizu 890ddd
	int col = objId.getIndex();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int frame = app->getCurrentFrame()->getFrame();
Toshihiro Shimizu 890ddd
	if (m_currentFrame != frame)
Toshihiro Shimizu 890ddd
		m_temporaryPinnedColumns.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TAffine aff = getMatrix();
Toshihiro Shimizu 890ddd
	// puo' suggere che il placement degeneri (es.: c'e' uno h-scale = 0%)
Toshihiro Shimizu 890ddd
	if (fabs(aff.det()) < 0.00001)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// m_unit = getPixelSize() * sqrt(fabs(aff.det()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!ikEnabled)
Toshihiro Shimizu 890ddd
		drawLevelBoundingBox(frame, col);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glPushMatrix();
Toshihiro Shimizu 890ddd
	tglMultMatrix(aff.inv());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// camera stand reference system
Toshihiro Shimizu 890ddd
	//glColor3d(0,1,0);
Toshihiro Shimizu 890ddd
	//tglDrawRect(0,0,100,100);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool changingParent = dynamic_cast<parentchangetool *="">(m_dragTool) != 0;</parentchangetool>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// !changingParent &&
Toshihiro Shimizu 890ddd
	if (m_mode.getValue() == BUILD_SKELETON && !xsh->getStageObjectParent(objId).isColumn()) {
Toshihiro Shimizu 890ddd
		if (!changingParent)
Toshihiro Shimizu 890ddd
			drawHooks();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Skeleton skeleton;
Toshihiro Shimizu 890ddd
	buildSkeleton(skeleton, col);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glEnable(GL_BLEND);
Toshihiro Shimizu 890ddd
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Toshihiro Shimizu 890ddd
	drawSkeleton(skeleton, frame);
Toshihiro Shimizu 890ddd
	glDisable(GL_BLEND);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXshCell cell = xsh->getCell(frame, objId.getIndex());
Toshihiro Shimizu 890ddd
	Skeleton::Bone *rootBone = skeleton.getRootBone();
Toshihiro Shimizu 890ddd
	for (int i = 0; i < skeleton.getBoneCount(); i++) {
Toshihiro Shimizu 890ddd
		Skeleton::Bone *bone = skeleton.getBone(i);
Toshihiro Shimizu 890ddd
		TStageObjectId currentId = bone->getStageObject()->getId();
Toshihiro Shimizu 890ddd
		bool isCurrent = (currentId == objId);
Toshihiro Shimizu 890ddd
		TPointD pos = bone->getCenter();
Toshihiro Shimizu 890ddd
		if (isCurrent && m_mode.getValue() != BUILD_SKELETON) {
Toshihiro Shimizu 890ddd
			drawDrawingBrowser(cell, pos);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		bool isActiveChain = bone->isSelected();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glColor3d(0, 1, 0);
Toshihiro Shimizu 890ddd
		if (ikEnabled) {
Toshihiro Shimizu 890ddd
			drawIKJoint(bone);
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			TPointD pos = bone->getCenter();
Toshihiro Shimizu 890ddd
			if (isCurrent && m_mode.getValue() == ANIMATE) {
Toshihiro Shimizu 890ddd
				drawMainGadget(pos);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	m_currentFrame = frame;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_dragTool)
Toshihiro Shimizu 890ddd
		m_dragTool->draw();
Toshihiro Shimizu 890ddd
	glPopMatrix();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::onActivate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTool::Application *app = TTool::getApplication();
Toshihiro Shimizu 890ddd
	if (m_firstTime) {
Toshihiro Shimizu 890ddd
		m_globalKeyframes.setValue(SkeletonGlobalKeyFrame ? 1 : 0);
Toshihiro Shimizu 890ddd
		m_mode.setValue(BUILD_SKELETON);
Toshihiro Shimizu 890ddd
		// m_ikEnabled.setValue(SkeletonInverseKinematics ? 1 : 0);
Toshihiro Shimizu 890ddd
		m_firstTime = false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TStageObjectId objId = app->getCurrentObject()->getObjectId();
Toshihiro Shimizu 890ddd
	if (objId == TStageObjectId::NoneId) {
Toshihiro Shimizu 890ddd
		int index = app->getCurrentColumn()->getColumnIndex();
Toshihiro Shimizu 890ddd
		objId = TStageObjectId::ColumnId(index);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	//  app->editStageObject(objId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::onDeactivate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//m_selection.selectNone();
Toshihiro Shimizu 890ddd
	//TSelection::setCurrent(0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
SkeletonSubtools::MagicLink SkeletonTool::getMagicLink(int index) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(0 <= index && index < (int)m_magicLinks.size());
Toshihiro Shimizu 890ddd
	return m_magicLinks[index];
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::magicLink(int index)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (index < 0 || index >= (int)m_magicLinks.size())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	HookData h0 = m_magicLinks[index].m_h0;
Toshihiro Shimizu 890ddd
	HookData h1 = m_magicLinks[index].m_h1;
Toshihiro Shimizu 890ddd
	TTool::Application *app = TTool::getApplication();
Toshihiro Shimizu 890ddd
	TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
	int columnIndex = app->getCurrentColumn()->getColumnIndex();
Toshihiro Shimizu 890ddd
	TStageObjectId id = TStageObjectId::ColumnId(columnIndex);
Toshihiro Shimizu 890ddd
	TStageObject *obj = xsh->getStageObject(id);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int parentColumnIndex = h1.m_columnIndex;
Toshihiro Shimizu 890ddd
	TStageObjectId parentId = TStageObjectId::ColumnId(parentColumnIndex);
Toshihiro Shimizu 890ddd
	std::string parentHandle = h1.getHandle();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::string handle = "";
Toshihiro Shimizu 890ddd
	if (h0.m_columnIndex < 0) {
Toshihiro Shimizu 890ddd
		handle = obj->getHandle();
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		handle = h0.getHandle();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//TUndoManager *undoManager = TUndoManager::manager();
Toshihiro Shimizu 890ddd
	//undoManager->beginBlock();
Toshihiro Shimizu 890ddd
	TStageObjectCmd::setHandle(id, handle, app->getCurrentXsheet());
Toshihiro Shimizu 890ddd
	TStageObjectCmd::setParent(id, parentId, parentHandle, app->getCurrentXsheet());
Toshihiro Shimizu 890ddd
	//undoManager->endBlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int SkeletonTool::getCursorId() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	switch (m_device) {
Toshihiro Shimizu 890ddd
	case TD_None:
Toshihiro Shimizu 890ddd
		if (m_mode.getValue() == BUILD_SKELETON)
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			return ToolCursor::RotCursor;
Toshihiro Shimizu 890ddd
	case TD_Translation:
Toshihiro Shimizu 890ddd
		return ToolCursor::MoveCursor;
Toshihiro Shimizu 890ddd
	case TD_Rotation:
Toshihiro Shimizu 890ddd
		return ToolCursor::RotCursor;
Toshihiro Shimizu 890ddd
	default:
Toshihiro Shimizu 890ddd
		return ToolCursor::StrokeSelectCursor;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return ToolCursor::StrokeSelectCursor;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::addContextMenuItems(QMenu *menu)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	bool ikEnabled = m_mode.getValue() == INVERSE_KINEMATICS;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (ikEnabled) {
Toshihiro Shimizu 890ddd
		Skeleton *skeleton = new Skeleton();
Toshihiro Shimizu 890ddd
		buildSkeleton(*skeleton, TTool::getApplication()->getCurrentColumn()->getColumnIndex());
Toshihiro Shimizu 890ddd
		if (skeleton->hasPinnedRanges() || skeleton->isIKEnabled()) {
Toshihiro Shimizu 890ddd
			m_commandHandler->setSkeleton(skeleton);
Toshihiro Shimizu 890ddd
			QAction *rp = menu->addAction(tr("Reset Pinned Center"));
Toshihiro Shimizu 890ddd
			menu->addSeparator();
Toshihiro Shimizu 890ddd
			bool ret = QObject::connect(
Toshihiro Shimizu 890ddd
				rp, SIGNAL(triggered()),
Toshihiro Shimizu 890ddd
				m_commandHandler, SLOT(clearPinnedRanges()));
Toshihiro Shimizu 890ddd
			assert(ret);
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			delete skeleton;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SkeletonTool::buildSkeleton(Skeleton &skeleton, int columnIndex)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int frame = TTool::getApplication()->getCurrentFrame()->getFrame();
Toshihiro Shimizu 890ddd
	skeleton.build(getXsheet(), frame, columnIndex, m_temporaryPinnedColumns);
Toshihiro Shimizu 890ddd
}