Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//  pinchtool.cpp
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//  ChangeLog:
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//    24/04/2005  Fab
Toshihiro Shimizu 890ddd
//                  Refactoring:
Toshihiro Shimizu 890ddd
//                    - removed unused headers
Toshihiro Shimizu 890ddd
//                    - changed zero finder algorithm (secant vs bisection)
Toshihiro Shimizu 890ddd
//    22/05/2005  Fab
Toshihiro Shimizu 890ddd
//                  Added header file.
Toshihiro Shimizu 890ddd
//                  Added adapting dragger.
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//    12/06/2005  Fab
Toshihiro Shimizu 890ddd
//                  Changed deformator API.
Toshihiro Shimizu 890ddd
//                  Added designer for dragger.
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
#define _STLP_DEBUG 1
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tools/toolutils.h"
Toshihiro Shimizu 890ddd
#include "tools/toolhandle.h"
Toshihiro Shimizu 890ddd
#include "tools/cursors.h"
Toshihiro Shimizu 890ddd
#include "tdebugmessage.h"
Toshihiro Shimizu 890ddd
#include "tgeometry.h"
Toshihiro Shimizu 890ddd
#include "tgl.h"
Toshihiro Shimizu 890ddd
#include "tproperty.h"
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
#include "tstrokeutil.h"
Toshihiro Shimizu 890ddd
#include "tthreadmessage.h"
Toshihiro Shimizu 890ddd
#include "tools/pinchtool.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/tobjecthandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshlevelhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobject.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "ext/StrokeDeformation.h"
Toshihiro Shimizu 890ddd
#include "ext/SmoothDeformation.h"
Toshihiro Shimizu 890ddd
#include "ext/OverallDesigner.h"
Toshihiro Shimizu 890ddd
#include "ext/ExtUtil.h"
Toshihiro Shimizu 890ddd
#include "ext/Selector.h"
Toshihiro Shimizu 890ddd
#include "ext/CornerDeformation.h"
Toshihiro Shimizu 890ddd
#include "ext/StraightCornerDeformation.h"
Toshihiro Shimizu 890ddd
#include "ext/StrokeDeformation.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <memory></memory>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace ToolUtils;
Toshihiro Shimizu 890ddd
using namespace ToonzExt;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// viene usato??
Toshihiro Shimizu 890ddd
class TGlobalChange;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct GLMatrixGuard {
Toshihiro Shimizu 890ddd
	GLMatrixGuard() { glPushMatrix(); }
Toshihiro Shimizu 890ddd
	~GLMatrixGuard() { glPopMatrix(); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PinchTool::PinchTool()
Toshihiro Shimizu 890ddd
	: TTool("T_Pinch"), m_active(false), m_cursorEnabled(false), m_draw(false), m_undo(0), m_showSelector(true), m_toolRange("Size:", 1.0, 1000.0, 500.0) // W_ToolOptions_PinchTool
Toshihiro Shimizu 890ddd
	  ,
Toshihiro Shimizu 890ddd
	  m_toolCornerSize("Corner:", 1.0, 180.0, 160.0) // W_ToolOptions_PinchCorner
Toshihiro Shimizu 890ddd
	  ,
Toshihiro Shimizu 890ddd
	  m_autoOrManual("Manual", false) // W_ToolOptions_PinchManual
Toshihiro Shimizu 890ddd
	  ,
Toshihiro Shimizu 890ddd
	  m_deformation(new ToonzExt::StrokeDeformation), m_selector(500, 10, 1000)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	bind(TTool::Vectors);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_prop.bind(m_toolCornerSize);
Toshihiro Shimizu 890ddd
	m_prop.bind(m_autoOrManual);
Toshihiro Shimizu 890ddd
	m_prop.bind(m_toolRange);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	CornerDeformation::instance()->setCursorId(ToolCursor::PinchWaveCursor);
Toshihiro Shimizu 890ddd
	SmoothDeformation::instance()->setCursorId(ToolCursor::PinchCursor);
Toshihiro Shimizu 890ddd
	StraightCornerDeformation::instance()->setCursorId(ToolCursor::PinchAngleCursor);
Toshihiro Shimizu 890ddd
	assert(m_deformation && "Can not create a deformation CATASTROFIC!!!");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TMouseEvent dummy;
Toshihiro Shimizu 890ddd
	updateInterfaceStatus(dummy);
Toshihiro Shimizu 890ddd
	m_autoOrManual.setId("Manual");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PinchTool::~PinchTool()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_deformation;
Toshihiro Shimizu 890ddd
	m_deformation = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PinchTool::updateTranslation()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_toolRange.setQStringName(tr("Size:"));
Toshihiro Shimizu 890ddd
	m_toolCornerSize.setQStringName(tr("Corner:"));
Toshihiro Shimizu 890ddd
	m_autoOrManual.setQStringName(tr("Manual"));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke *PinchTool::getClosestStroke(const TPointD &pos, double &w) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi = TImageP(getImage(false));
Toshihiro Shimizu 890ddd
	if (!vi)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
	double dist = 0;
Toshihiro Shimizu 890ddd
	UINT index;
Toshihiro Shimizu 890ddd
	if (vi->getNearestStroke(pos, w, index, dist, true))
Toshihiro Shimizu 890ddd
		return vi->getStroke(index);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PinchTool::updateInterfaceStatus(const TMouseEvent &event)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(getPixelSize() > 0 && "Pixel size is lower than 0!!!");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_status.isManual_ = m_autoOrManual.getValue();
Toshihiro Shimizu 890ddd
	m_status.pixelSize_ = getPixelSize();
Toshihiro Shimizu 890ddd
	m_status.cornerSize_ = (int)m_toolCornerSize.getValue();
Toshihiro Shimizu 890ddd
	m_status.lengthOfAction_ = m_toolRange.getValue();
Toshihiro Shimizu 890ddd
	m_status.deformerSensibility_ = 0.01 * getPixelSize();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_status.key_event_ = ContextStatus::NONE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// mutual exclusive
Toshihiro Shimizu 890ddd
	if (event.isCtrlPressed())
Toshihiro Shimizu 890ddd
		m_status.key_event_ = ContextStatus::CTRL;
Toshihiro Shimizu 890ddd
	if (event.isShiftPressed())
Toshihiro Shimizu 890ddd
		m_status.key_event_ = ContextStatus::SHIFT;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// TODO:  **DEVE** essere fatto dentro la costruzione di TMouseEvent
Toshihiro Shimizu 890ddd
	// nel codice di Toonz/Tab/ecc. **NON** ci devono essere ifdef MACOSX se e' possibile
Toshihiro Shimizu 890ddd
	// evitarlo. Qua sotto ci deve essere solo if(event.isShiftPressed)
Toshihiro Shimizu 890ddd
	/*#ifdef MACOSX
Toshihiro Shimizu 890ddd
  if(event.isLockPressed() )
Toshihiro Shimizu 890ddd
#else*/
Toshihiro Shimizu 890ddd
	if (event.isAltPressed())
Toshihiro Shimizu 890ddd
		//#endif
Toshihiro Shimizu 890ddd
		m_status.key_event_ = ContextStatus::ALT;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_selector.setStroke(0);
Toshihiro Shimizu 890ddd
	m_selector.setVisibility(m_status.isManual_ && m_showSelector);
Toshihiro Shimizu 890ddd
	m_selector.setLength(m_status.lengthOfAction_);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PinchTool::updateStrokeStatus(TStroke *stroke, double w)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(stroke && "Stroke is null!!!");
Toshihiro Shimizu 890ddd
	assert(0.0 <= w && w <= 1.0 && "Stroke's parameter is out of range [0,1]!!!");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!stroke || w < 0.0 || w > 1.0)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// start update the status
Toshihiro Shimizu 890ddd
	m_status.stroke2change_ = stroke;
Toshihiro Shimizu 890ddd
	m_status.w_ = w;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(stroke->getLength() >= 0.0 && "Wrong length in stroke!!!");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int PinchTool::updateCursor() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!(TVectorImageP)getImage(false))
Toshihiro Shimizu 890ddd
		return ToolCursor::CURSOR_NO;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return m_deformation->getCursorId();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PinchTool::leftButtonDown(const TPointD &pos,
Toshihiro Shimizu 890ddd
							   const TMouseEvent &event)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_curr = m_down = pos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_active &&
Toshihiro Shimizu 890ddd
		!m_selector.isSelected()) {
Toshihiro Shimizu 890ddd
		m_active = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(m_undo == 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		StrokeDeformation *
Toshihiro Shimizu 890ddd
			deformation = m_deformation;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TVectorImageP
Toshihiro Shimizu 890ddd
			vi = TImageP(getImage(true));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!vi)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_active = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		ContextStatus
Toshihiro Shimizu 890ddd
			*status = &m_status;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// reset status
Toshihiro Shimizu 890ddd
		status->init();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double
Toshihiro Shimizu 890ddd
			w,
Toshihiro Shimizu 890ddd
			dist2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// find nearest stroke
Toshihiro Shimizu 890ddd
		if (vi->getNearestStroke(m_down,
Toshihiro Shimizu 890ddd
								 w,
Toshihiro Shimizu 890ddd
								 m_n,
Toshihiro Shimizu 890ddd
								 dist2, true)) {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TStroke
Toshihiro Shimizu 890ddd
				*stroke = vi->getStroke(m_n);
Toshihiro Shimizu 890ddd
			assert(stroke && "Not valid stroke found!!!");
Toshihiro Shimizu 890ddd
			if (!stroke)
Toshihiro Shimizu 890ddd
				return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			updateStrokeStatus(stroke,
Toshihiro Shimizu 890ddd
							   w);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// set parameters from sliders
Toshihiro Shimizu 890ddd
			updateInterfaceStatus(event);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			deformation->activate(status);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// stroke can be changed (replaced by another) during deformation activate
Toshihiro Shimizu 890ddd
			if (TTool::getApplication()->getCurrentObject()->isSpline())
Toshihiro Shimizu 890ddd
				m_undo = new ToolUtils::UndoPath(getXsheet()->getStageObject(getObjectId())->getSpline());
Toshihiro Shimizu 890ddd
			else {
Toshihiro Shimizu 890ddd
				TXshSimpleLevel *sl = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
				assert(sl);
Toshihiro Shimizu 890ddd
				TFrameId id = getCurrentFid();
Toshihiro Shimizu 890ddd
				m_undo = new UndoModifyStrokeAndPaint(sl, id, m_n);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_selector.mouseDown(m_curr);
Toshihiro Shimizu 890ddd
	m_prev = m_curr;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PinchTool::leftButtonDrag(const TPointD &pos,
Toshihiro Shimizu 890ddd
							   const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_curr = pos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_selector.isSelected()) {
Toshihiro Shimizu 890ddd
		m_selector.mouseDrag(m_curr);
Toshihiro Shimizu 890ddd
		TDoubleProperty::Range
Toshihiro Shimizu 890ddd
			prop_range = m_toolRange.getRange();
Toshihiro Shimizu 890ddd
		double
Toshihiro Shimizu 890ddd
			val_in_range = m_selector.getLength();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// set value in range
Toshihiro Shimizu 890ddd
		val_in_range = max(min(val_in_range, prop_range.second), prop_range.first);
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			m_toolRange.setValue(val_in_range);
Toshihiro Shimizu 890ddd
			TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Toshihiro Shimizu 890ddd
		} catch (TDoubleProperty::RangeError &) {
Toshihiro Shimizu 890ddd
			m_toolRange.setValue((prop_range.first + prop_range.second) * 0.5);
Toshihiro Shimizu 890ddd
			TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_selector.setLength(m_toolRange.getValue());
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		TVectorImageP
Toshihiro Shimizu 890ddd
			vi(getImage(true));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		ContextStatus
Toshihiro Shimizu 890ddd
			*status = &m_status;
Toshihiro Shimizu 890ddd
		if (!vi ||
Toshihiro Shimizu 890ddd
			!status->stroke2change_ ||
Toshihiro Shimizu 890ddd
			!m_active)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		QMutexLocker lock(vi->getMutex());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//assert( status->stroke2change_->getLength() >= 0.0 );
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		StrokeDeformation *
Toshihiro Shimizu 890ddd
			deformation = m_deformation;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TPointD
Toshihiro Shimizu 890ddd
			delta = m_curr - m_prev;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		deformation->update(delta);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_prev = m_curr;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//moveCursor(pos);
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PinchTool::leftButtonUp(const TPointD &pos,
Toshihiro Shimizu 890ddd
							 const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_active ||
Toshihiro Shimizu 890ddd
		m_selector.isSelected())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_active = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TVectorImageP
Toshihiro Shimizu 890ddd
		vi(getImage(true));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ContextStatus
Toshihiro Shimizu 890ddd
		*status = &m_status;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!vi ||
Toshihiro Shimizu 890ddd
		!status->stroke2change_) {
Toshihiro Shimizu 890ddd
		delete m_undo;
Toshihiro Shimizu 890ddd
		m_undo = 0;
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// if mouse position is unchanged doesn't modify current stroke
Toshihiro Shimizu 890ddd
	if (areAlmostEqual(m_down,
Toshihiro Shimizu 890ddd
					   pos,
Toshihiro Shimizu 890ddd
					   PickRadius * status->pixelSize_)) {
Toshihiro Shimizu 890ddd
		assert(m_undo);
Toshihiro Shimizu 890ddd
		delete m_undo;
Toshihiro Shimizu 890ddd
		m_undo = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// to avoid red line tool on stroke
Toshihiro Shimizu 890ddd
#ifdef WIN32
Toshihiro Shimizu 890ddd
		invalidate(status->stroke2change_->getBBox().enlarge(status->pixelSize_ * 13));
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
		m_deformation->deactivate();
Toshihiro Shimizu 890ddd
		status->stroke2change_ = 0;
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QMutexLocker lock(vi->getMutex());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TStroke *deactivateStroke = m_deformation->deactivate();
Toshihiro Shimizu 890ddd
	deactivateStroke->outlineOptions() = status->stroke2change_->outlineOptions();
Toshihiro Shimizu 890ddd
	replaceStroke(status->stroke2change_,
Toshihiro Shimizu 890ddd
				  deactivateStroke,
Toshihiro Shimizu 890ddd
				  m_n,
Toshihiro Shimizu 890ddd
				  vi);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	status->stroke2change_ = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	vi->notifyChangedStrokes(m_n);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
	vi->checkIntersections();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
	vi->checkIntersections();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	moveCursor(pos);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	notifyImageChanged();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(m_undo);
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->add(m_undo);
Toshihiro Shimizu 890ddd
	m_undo = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PinchTool::onEnter()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_draw = true;
Toshihiro Shimizu 890ddd
	// per sicurezza
Toshihiro Shimizu 890ddd
	//m_status.stroke2change_ = 0;
Toshihiro Shimizu 890ddd
	//m_selector.setStroke(0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PinchTool::onLeave()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_active)
Toshihiro Shimizu 890ddd
		m_draw = false;
Toshihiro Shimizu 890ddd
	m_status.stroke2change_ = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Abbiamo dovuto commentarlo perche' stranamente
Toshihiro Shimizu 890ddd
	// l'onLeave viene chiamata anche quando viene premuto il tasto del mouse
Toshihiro Shimizu 890ddd
	// per iniziare a fare drag utilizzando il Selector
Toshihiro Shimizu 890ddd
	// setStroke al suo interno resetta lo status del Selector (lo mette a NONE)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//  m_selector.setStroke(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_deformation->reset();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PinchTool::onImageChanged()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_status.stroke2change_ = 0;
Toshihiro Shimizu 890ddd
	m_deformation->reset();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double w = 0;
Toshihiro Shimizu 890ddd
	TStroke *stroke = getClosestStroke(convert(m_lastMouseEvent.m_pos), w);
Toshihiro Shimizu 890ddd
	if (stroke) {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// set parameters from sliders
Toshihiro Shimizu 890ddd
		updateInterfaceStatus(m_lastMouseEvent);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// update information about current stroke
Toshihiro Shimizu 890ddd
		updateStrokeStatus(stroke, w);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_selector.setStroke(stroke);
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PinchTool::draw()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	GLMatrixGuard guard;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TVectorImageP img(getImage(true));
Toshihiro Shimizu 890ddd
	if (!img || img->getStrokeCount() == 0) //Controllo che il numero degli stroke nell'immagine sia != 0
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	if (!m_draw)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ContextStatus *
Toshihiro Shimizu 890ddd
		status = &m_status;
Toshihiro Shimizu 890ddd
	if (!status)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	StrokeDeformation *
Toshihiro Shimizu 890ddd
		deformation = m_deformation;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	OverallDesigner
Toshihiro Shimizu 890ddd
	designer((int)m_curr.x,
Toshihiro Shimizu 890ddd
			 (int)m_curr.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// m_active == true means that a button down is done (drag)
Toshihiro Shimizu 890ddd
	if (!m_active) {
Toshihiro Shimizu 890ddd
		if (m_cursorEnabled) {
Toshihiro Shimizu 890ddd
			glColor3d(1, 0, 1);
Toshihiro Shimizu 890ddd
			if (m_cursor.thick > 0)
Toshihiro Shimizu 890ddd
				tglDrawCircle(m_cursor,
Toshihiro Shimizu 890ddd
							  m_cursor.thick);
Toshihiro Shimizu 890ddd
			tglDrawCircle(m_cursor,
Toshihiro Shimizu 890ddd
						  m_cursor.thick + 4 * status->pixelSize_);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// internal deformer can be changed during draw
Toshihiro Shimizu 890ddd
	if (!m_selector.isSelected())
Toshihiro Shimizu 890ddd
		deformation->draw(&designer);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_selector.draw(&designer);
Toshihiro Shimizu 890ddd
	CHECK_ERRORS_BY_GL;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PinchTool::invalidateCursorArea()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double r = m_cursor.thick + 6;
Toshihiro Shimizu 890ddd
	TPointD d(r, r);
Toshihiro Shimizu 890ddd
	invalidate(TRectD(m_cursor - d, m_cursor + d));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PinchTool::mouseMove(const TPointD &pos,
Toshihiro Shimizu 890ddd
						  const TMouseEvent &event)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_active)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_draw)
Toshihiro Shimizu 890ddd
		m_draw = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ContextStatus *status = &m_status;
Toshihiro Shimizu 890ddd
	m_curr = pos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const int pixelRange = 3;
Toshihiro Shimizu 890ddd
	if (abs(m_lastMouseEvent.m_pos.x - event.m_pos.x) < pixelRange &&
Toshihiro Shimizu 890ddd
		abs(m_lastMouseEvent.m_pos.y - event.m_pos.y) < pixelRange &&
Toshihiro Shimizu 890ddd
		m_lastMouseEvent.getModifiersMask() == event.getModifiersMask())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_lastMouseEvent = event;
Toshihiro Shimizu 890ddd
	double w = 0;
Toshihiro Shimizu 890ddd
	TStroke *stroke = getClosestStroke(pos, w);
Toshihiro Shimizu 890ddd
	if (stroke) {
Toshihiro Shimizu 890ddd
		// set parameters from sliders
Toshihiro Shimizu 890ddd
		updateInterfaceStatus(event);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// update information about current stroke
Toshihiro Shimizu 890ddd
		updateStrokeStatus(stroke, w);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// retrieve the currect m_deformation and
Toshihiro Shimizu 890ddd
		// prepare to design and modify
Toshihiro Shimizu 890ddd
		if (m_deformation)
Toshihiro Shimizu 890ddd
			m_deformation->check(status);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_selector.setStroke(stroke);
Toshihiro Shimizu 890ddd
		m_selector.mouseMove(m_curr);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		m_status.stroke2change_ = 0;
Toshihiro Shimizu 890ddd
		m_selector.setStroke(0);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_prev = m_curr;
Toshihiro Shimizu 890ddd
	m_cursorEnabled = moveCursor(pos);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_cursorEnabled)
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//  TNotifier::instance()->notify(TToolChange());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool PinchTool::keyDown(int key,
Toshihiro Shimizu 890ddd
						TUINT32 flags,
Toshihiro Shimizu 890ddd
						const TPoint &pos)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_deformation->reset();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if 0
Toshihiro Shimizu 890ddd
  char c = (char)key;
Toshihiro Shimizu 890ddd
  if(c == 'p' ||
Toshihiro Shimizu 890ddd
     c == 'P' )
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    TVectorImageP vimage(getImage());      
Toshihiro Shimizu 890ddd
    if(!vimage)
Toshihiro Shimizu 890ddd
      return false;
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
    char  fileName[] = {"c:\\toonz_input.sdd"};
Toshihiro Shimizu 890ddd
    ofstream  out_file(fileName);
Toshihiro Shimizu 890ddd
    if(!out_file)
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
      cerr<<"Error on opening: "<
Toshihiro Shimizu 890ddd
      return false;
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
    out_file<<"# VImage info\n";
Toshihiro Shimizu 890ddd
    out_file<<"# Number of stroke:\n";
Toshihiro Shimizu 890ddd
    const int max_number_of_strokes = vimage->getStrokeCount();
Toshihiro Shimizu 890ddd
    out_file<
Toshihiro Shimizu 890ddd
    int number_of_strokes = 0;
Toshihiro Shimizu 890ddd
    const int cp_for_row=3;
Toshihiro Shimizu 890ddd
    while( number_of_strokes
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
      TStroke* ref = vimage->getStroke(number_of_strokes);
Toshihiro Shimizu 890ddd
      out_file<
Toshihiro Shimizu 890ddd
      out_file<<"# Number of control points for stroke:\n";
Toshihiro Shimizu 890ddd
      const int max_number_of_cp = ref->getControlPointCount();
Toshihiro Shimizu 890ddd
      out_file<
Toshihiro Shimizu 890ddd
      out_file<<"# Control Points:\n";
Toshihiro Shimizu 890ddd
      int number_of_cp=0;
Toshihiro Shimizu 890ddd
      while( number_of_cp
Toshihiro Shimizu 890ddd
      {
Toshihiro Shimizu 890ddd
        out_file<<ref->getControlPoint(number_of_cp)<<" ";</ref->
Toshihiro Shimizu 890ddd
        if(!((number_of_cp+1)%cp_for_row)) // add a new line after ten points
Toshihiro Shimizu 890ddd
          out_file<
Toshihiro Shimizu 890ddd
        number_of_cp++;
Toshihiro Shimizu 890ddd
      }
Toshihiro Shimizu 890ddd
      out_file<
Toshihiro Shimizu 890ddd
      number_of_strokes++;
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool PinchTool::moveCursor(const TPointD &pos)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double w = 0.0;
Toshihiro Shimizu 890ddd
	TStroke *stroke = getClosestStroke(pos, w);
Toshihiro Shimizu 890ddd
	if (!stroke)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_cursor = stroke->getThickPoint(w);
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PinchTool::onActivate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//  getApplication()->editImageOrSpline();
Toshihiro Shimizu 890ddd
	//  TNotifier::instance()->attach(this);
Toshihiro Shimizu 890ddd
	// per sicurezza
Toshihiro Shimizu 890ddd
	m_status.stroke2change_ = 0;
Toshihiro Shimizu 890ddd
	m_selector.setStroke(0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PinchTool::onDeactivate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_draw = false;
Toshihiro Shimizu 890ddd
	delete m_undo;
Toshihiro Shimizu 890ddd
	m_undo = 0;
Toshihiro Shimizu 890ddd
	m_active = false;
Toshihiro Shimizu 890ddd
	m_deformation->reset();
Toshihiro Shimizu 890ddd
	//  TNotifier::instance()->detach(this);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PinchTool::update(const TGlobalChange &)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_cursor = TConsts::natp;
Toshihiro Shimizu 890ddd
	m_selector.setStroke(0);
Toshihiro Shimizu 890ddd
	m_selector.setVisibility(m_autoOrManual.getValue() && m_showSelector);
Toshihiro Shimizu 890ddd
	if (m_deformation)
Toshihiro Shimizu 890ddd
		delete m_deformation->deactivate();
Toshihiro Shimizu 890ddd
	// per sicurezza
Toshihiro Shimizu 890ddd
	m_status.stroke2change_ = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static PinchTool pinchTool;