Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tundo.h"
Toshihiro Shimizu 890ddd
#include "tthreadmessage.h"
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
#include "drawutil.h"
Toshihiro Shimizu 890ddd
#include "controlpointselection.h"
Toshihiro Shimizu 890ddd
#include "tproperty.h"
Toshihiro Shimizu 890ddd
#include "tenv.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tools/tool.h"
Toshihiro Shimizu 890ddd
#include "tools/toolutils.h"
Toshihiro Shimizu 890ddd
#include "tools/cursors.h"
Toshihiro Shimizu 890ddd
#include "tools/toolhandle.h"
Toshihiro Shimizu 890ddd
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/txshlevelhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tobjecthandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/stage2.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobject.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tw/keycodes.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// For Qt translation support
Toshihiro Shimizu 890ddd
#include <qcoreapplication></qcoreapplication>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace ToolUtils;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TEnv::IntVar AutoSelectDrawing("ControlPointEditorToolAutoSelectDrawing", 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! Restituisce i parametri riferiti allo stroke della curva che si vuole muovere.
Toshihiro Shimizu 890ddd
    I parametri dipendono da come sono i punti in \b beforeIndex, \b nextIndex (cuspidi, lineari).
Toshihiro Shimizu 890ddd
    Puo' restituire due range nei casi in cui lo stroke e' selfLoop e la curva e' a cavallo del punto di chiusura.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
void getSegmentParameter(ControlPointEditorStroke *cpEditor, int beforeIndex, int nextIndex,
Toshihiro Shimizu 890ddd
						 double &w0, double &w1, double &q0, double &q1)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TStroke *stroke = cpEditor->getStroke();
Toshihiro Shimizu 890ddd
	if (!stroke)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	q0 = q1 = w0 = w1 = -1;
Toshihiro Shimizu 890ddd
	int cpCount = cpEditor->getControlPointCount();
Toshihiro Shimizu 890ddd
	//Il punto di controllo precedente non e' lincato
Toshihiro Shimizu 890ddd
	if (cpEditor->isSpeedOutLinear(beforeIndex) || cpEditor->isSpeedInLinear(beforeIndex) || cpEditor->isCusp(beforeIndex)) {
Toshihiro Shimizu 890ddd
		if (cpEditor->isSelfLoop() && beforeIndex == 0 && nextIndex == cpCount - 1) //Nel caso selfLoop si invertono i valori
Toshihiro Shimizu 890ddd
			w1 = 1;
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			w0 = stroke->getParameterAtControlPoint(cpEditor->getIndexPointInStroke(beforeIndex));
Toshihiro Shimizu 890ddd
	} else //Punto di controllo precedente lincato
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (!cpEditor->isSelfLoop() || beforeIndex != 0)
Toshihiro Shimizu 890ddd
			w0 = stroke->getParameterAtControlPoint(cpEditor->getIndexPointInStroke(beforeIndex) - 4);
Toshihiro Shimizu 890ddd
		else {
Toshihiro Shimizu 890ddd
			if (nextIndex == 1) //Primo chunk
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				w0 = 0;
Toshihiro Shimizu 890ddd
				q0 = stroke->getParameterAtControlPoint(cpEditor->getIndexPointInStroke(cpCount - 1));
Toshihiro Shimizu 890ddd
				q1 = 1;
Toshihiro Shimizu 890ddd
			} else if (nextIndex == cpCount - 1) //Ultimo chunk
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				w1 = 1;
Toshihiro Shimizu 890ddd
				q0 = 0;
Toshihiro Shimizu 890ddd
				q1 = stroke->getParameterAtControlPoint(cpEditor->getIndexPointInStroke(1));
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				assert(0);
Toshihiro Shimizu 890ddd
			} //Non dovrebbe mai accadere
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	//Il punto di controllo successivo non e' lincato
Toshihiro Shimizu 890ddd
	if (cpEditor->isSpeedInLinear(nextIndex) || cpEditor->isSpeedOutLinear(nextIndex) || cpEditor->isCusp(nextIndex)) {
Toshihiro Shimizu 890ddd
		if (cpEditor->isSelfLoop() && beforeIndex == 0 && nextIndex == cpCount - 1) //Nel caso selfLoop si invertono i valori
Toshihiro Shimizu 890ddd
			w0 = stroke->getParameterAtControlPoint(cpEditor->getIndexPointInStroke(nextIndex));
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			w1 = stroke->getParameterAtControlPoint(cpEditor->getIndexPointInStroke(nextIndex));
Toshihiro Shimizu 890ddd
	} else //Punto di controllo successivo lincato
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (!cpEditor->isSelfLoop() || nextIndex != cpCount - 1 || beforeIndex != 0)
Toshihiro Shimizu 890ddd
			w1 = stroke->getParameterAtControlPoint(cpEditor->getIndexPointInStroke(nextIndex) + 4);
Toshihiro Shimizu 890ddd
		else if (nextIndex == cpCount - 1) //Ultimo chunk
Toshihiro Shimizu 890ddd
			w0 = stroke->getParameterAtControlPoint(cpEditor->getIndexPointInStroke(nextIndex) - 4);
Toshihiro Shimizu 890ddd
		else {
Toshihiro Shimizu 890ddd
			assert(0);
Toshihiro Shimizu 890ddd
		} //Non dovrebbe mai accadere, i vari casi dovrebbero essere gestiti sopra
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} //namespace
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// ControlPointEditorTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class ControlPointEditorTool : public TTool
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	Q_DECLARE_TR_FUNCTIONS(ControlPointEditorTool)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool m_draw;
Toshihiro Shimizu 890ddd
	bool m_isMenuViewed;
Toshihiro Shimizu 890ddd
	int m_lastPointSelected;
Toshihiro Shimizu 890ddd
	bool m_isImageChanged;
Toshihiro Shimizu 890ddd
	ControlPointSelection m_selection;
Toshihiro Shimizu 890ddd
	ControlPointEditorStroke m_controlPointEditorStroke;
Toshihiro Shimizu 890ddd
	std::pair<int, int=""> m_moveSegmentLimitation;			 //Indici dei punti di controllo che limitano la curva da muovere</int,>
Toshihiro Shimizu 890ddd
	ControlPointEditorStroke m_moveControlPointEditorStroke; //Usate per muovere la curva durante il drag.
Toshihiro Shimizu 890ddd
	TRectD m_selectingRect;
Toshihiro Shimizu 890ddd
	TPointD m_pos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPropertyGroup m_prop;
Toshihiro Shimizu 890ddd
	TBoolProperty m_autoSelectDrawing; //Consente di scegliere se swichare tra i livelli.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	enum Action { NONE,
Toshihiro Shimizu 890ddd
				  RECT_SELECTION,
Toshihiro Shimizu 890ddd
				  CP_MOVEMENT,
Toshihiro Shimizu 890ddd
				  SEGMENT_MOVEMENT,
Toshihiro Shimizu 890ddd
				  IN_SPEED_MOVEMENT,
Toshihiro Shimizu 890ddd
				  OUT_SPEED_MOVEMENT };
Toshihiro Shimizu 890ddd
	Action m_action;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	enum CursorType { NORMAL,
Toshihiro Shimizu 890ddd
					  ADD,
Toshihiro Shimizu 890ddd
					  EDIT_SPEED,
Toshihiro Shimizu 890ddd
					  EDIT_SEGMENT,
Toshihiro Shimizu 890ddd
					  NO_ACTIVE };
Toshihiro Shimizu 890ddd
	CursorType m_cursorType;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TUndo *m_undo;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ControlPointEditorTool();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ToolType getToolType() const { return TTool::LevelWriteTool; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void updateTranslation();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPropertyGroup *getProperties(int targetType) { return &m_prop; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// da TSelectionOwner: chiamato quando la selezione corrente viene cambiata
Toshihiro Shimizu 890ddd
	void onSelectionChanged() { invalidate(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// da TSelectionOwner: chiamato quando si vuole ripristinare una vecchia selezione
Toshihiro Shimizu 890ddd
	// attualmente non usato
Toshihiro Shimizu 890ddd
	bool select(const TSelection *) { return false; }
Toshihiro Shimizu 890ddd
	ControlPointEditorStroke getControlPointEditorStroke() { return m_controlPointEditorStroke; };
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void initUndo();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void getNearestStrokeColumnIndexes(vector<int> &indexes, TPointD pos);</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void drawMovingSegment();
Toshihiro Shimizu 890ddd
	void drawControlPoint();
Toshihiro Shimizu 890ddd
	void draw();
Toshihiro Shimizu 890ddd
	void mouseMove(const TPointD &pos, const TMouseEvent &e);
Toshihiro Shimizu 890ddd
	void leftButtonDown(const TPointD &pos, const TMouseEvent &e);
Toshihiro Shimizu 890ddd
	void rightButtonDown(const TPointD &pos, const TMouseEvent &);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void moveControlPoints(const TPointD &delta);
Toshihiro Shimizu 890ddd
	void moveSpeed(const TPointD &delta, bool isIn);
Toshihiro Shimizu 890ddd
	void moveSegment(const TPointD &delta, bool dragging, bool isShiftPressed);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void leftButtonDrag(const TPointD &pos, const TMouseEvent &e);
Toshihiro Shimizu 890ddd
	void leftButtonUp(const TPointD &pos, const TMouseEvent &e);
Toshihiro Shimizu 890ddd
	void addContextMenuItems(QMenu *menu);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void linkSpeedInOut(int index);
Toshihiro Shimizu 890ddd
	void unlinkSpeedInOut(int pointIndex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool keyDown(int key, TUINT32 flags, const TPoint &pos);
Toshihiro Shimizu 890ddd
	void onEnter();
Toshihiro Shimizu 890ddd
	void onLeave();
Toshihiro Shimizu 890ddd
	bool onPropertyChanged(string propertyName);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void onActivate();
Toshihiro Shimizu 890ddd
	void onDeactivate();
Toshihiro Shimizu 890ddd
	void onImageChanged();
Toshihiro Shimizu 890ddd
	int getCursorId() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} controlPointEditorTool;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Spline Editor Tool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ControlPointEditorTool::ControlPointEditorTool()
Toshihiro Shimizu 890ddd
	: TTool("T_ControlPointEditor"), m_draw(false), m_lastPointSelected(-1), m_isImageChanged(false), m_selectingRect(TRectD()), m_autoSelectDrawing("Auto Select Drawing", true), m_action(NONE), m_cursorType(NORMAL), m_undo(0), m_isMenuViewed(false), m_moveControlPointEditorStroke(), m_moveSegmentLimitation()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	bind(TTool::Vectors);
Toshihiro Shimizu 890ddd
	m_prop.bind(m_autoSelectDrawing);
Toshihiro Shimizu 890ddd
	m_selection.setControlPointEditorStroke(&m_controlPointEditorStroke);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_autoSelectDrawing.setId("AutoSelectDrawing");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::updateTranslation()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_autoSelectDrawing.setQStringName(tr("Auto Select Drawing"));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::initUndo()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (TTool::getApplication()->getCurrentObject()->isSpline()) {
Toshihiro Shimizu 890ddd
		m_undo = new UndoPath(getXsheet()->getStageObject(getObjectId())->getSpline());
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TVectorImageP vi(getImage(false));
Toshihiro Shimizu 890ddd
	if (!vi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	TXshSimpleLevel *level = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
	UndoControlPointEditor *undo = new UndoControlPointEditor(level, getCurrentFid());
Toshihiro Shimizu 890ddd
	int index = m_controlPointEditorStroke.getStrokeIndex();
Toshihiro Shimizu 890ddd
	if (index > -1)
Toshihiro Shimizu 890ddd
		undo->addOldStroke(index, vi->getVIStroke(index));
Toshihiro Shimizu 890ddd
	m_undo = undo;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::getNearestStrokeColumnIndexes(vector<int> &indexes, TPointD pos)</int>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTool::Application *app = TTool::getApplication();
Toshihiro Shimizu 890ddd
	TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
	int currentFrame = app->getCurrentFrame()->getFrameIndex();
Toshihiro Shimizu 890ddd
	vector<int> newIndexes;</int>
Toshihiro Shimizu 890ddd
	TAffine aff = getMatrix();
Toshihiro Shimizu 890ddd
	int i = 0;
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)indexes.size(); i++) {
Toshihiro Shimizu 890ddd
		if (xsh->getColumn(i)->isLocked())
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		int index = indexes[i];
Toshihiro Shimizu 890ddd
		TVectorImageP vi = xsh->getCell(currentFrame, index).getImage(false);
Toshihiro Shimizu 890ddd
		if (!vi)
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		double dist2, t = 0;
Toshihiro Shimizu 890ddd
		UINT strokeIndex = -1;
Toshihiro Shimizu 890ddd
		TPointD p = getColumnMatrix(index).inv() * getMatrix() * pos;
Toshihiro Shimizu 890ddd
		if (vi->getNearestStroke(p, t, strokeIndex, dist2) && dist2 < 25 * getPixelSize() * getPixelSize())
Toshihiro Shimizu 890ddd
			newIndexes.push_back(index);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	indexes.clear();
Toshihiro Shimizu 890ddd
	indexes = newIndexes;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::drawMovingSegment()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int beforeIndex = m_moveSegmentLimitation.first;
Toshihiro Shimizu 890ddd
	int nextIndex = m_moveSegmentLimitation.second;
Toshihiro Shimizu 890ddd
	if (m_action != EDIT_SEGMENT || beforeIndex == -1 || nextIndex == -1 || !m_moveControlPointEditorStroke.getStroke())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	tglColor(TPixel::Green);
Toshihiro Shimizu 890ddd
	double w0, w1;
Toshihiro Shimizu 890ddd
	double q0, q1;
Toshihiro Shimizu 890ddd
	getSegmentParameter(&m_moveControlPointEditorStroke, beforeIndex, nextIndex, w0, w1, q0, q1);
Toshihiro Shimizu 890ddd
	if (w0 != -1 && w1 != -1) //Dovrebbero essere sempre diversi...
Toshihiro Shimizu 890ddd
		drawStrokeCenterline(*m_moveControlPointEditorStroke.getStroke(), getPixelSize(), w0, w1);
Toshihiro Shimizu 890ddd
	if (q0 != -1 && q1 != -1)
Toshihiro Shimizu 890ddd
		drawStrokeCenterline(*m_moveControlPointEditorStroke.getStroke(), getPixelSize(), q0, q1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::drawControlPoint()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPixel color1 = TPixel(79, 128, 255);
Toshihiro Shimizu 890ddd
	TPixel color2 = TPixel::White;
Toshihiro Shimizu 890ddd
	TPixel color_handle = TPixel(96, 64, 201);
Toshihiro Shimizu 890ddd
	int controlPointCount = m_controlPointEditorStroke.getControlPointCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double pix = getPixelSize() * 2.0f;
Toshihiro Shimizu 890ddd
	double pix1_5 = 1.5 * pix, pix2 = pix + pix, pix2_5 = pix1_5 + pix,
Toshihiro Shimizu 890ddd
		   pix3 = pix2 + pix, pix3_5 = pix2_5 + pix, pix4 = pix3 + pix;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double maxDist2 = sq(5.0 * pix);
Toshihiro Shimizu 890ddd
	double dist2 = 0;
Toshihiro Shimizu 890ddd
	int pointIndex;
Toshihiro Shimizu 890ddd
	ControlPointEditorStroke::PointType pointType = m_controlPointEditorStroke.getPointTypeAt(m_pos, maxDist2, pointIndex);
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < controlPointCount; i++) {
Toshihiro Shimizu 890ddd
		TThickPoint point = m_controlPointEditorStroke.getControlPoint(i);
Toshihiro Shimizu 890ddd
		TPointD pa = m_controlPointEditorStroke.getSpeedInPoint(i);
Toshihiro Shimizu 890ddd
		TPointD pb = m_controlPointEditorStroke.getSpeedOutPoint(i);
Toshihiro Shimizu 890ddd
		tglColor(color_handle);
Toshihiro Shimizu 890ddd
		tglDrawSegment(pa, point);
Toshihiro Shimizu 890ddd
		if (i == pointIndex && pointType == ControlPointEditorStroke::SPEED_IN)
Toshihiro Shimizu 890ddd
			tglFillRect(pa.x - pix2_5, pa.y - pix2_5, pa.x + pix2_5, pa.y + pix2_5);
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			tglFillRect(pa.x - pix1_5, pa.y - pix1_5, pa.x + pix1_5, pa.y + pix1_5);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		tglDrawSegment(pb, point);
Toshihiro Shimizu 890ddd
		if (i == pointIndex && pointType == ControlPointEditorStroke::SPEED_OUT)
Toshihiro Shimizu 890ddd
			tglFillRect(pb.x - pix2_5, pb.y - pix2_5, pb.x + pix2_5, pb.y + pix2_5);
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			tglFillRect(pb.x - pix1_5, pb.y - pix1_5, pb.x + pix1_5, pb.y + pix1_5);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		tglColor(color1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (i == pointIndex && pointType == ControlPointEditorStroke::CONTROL_POINT) {
Toshihiro Shimizu 890ddd
			tglFillRect(point.x - pix3_5, point.y - pix3_5, point.x + pix3_5, point.y + pix3_5);
Toshihiro Shimizu 890ddd
			if (!m_selection.isSelected(i)) {
Toshihiro Shimizu 890ddd
				tglColor(color2);
Toshihiro Shimizu 890ddd
				tglFillRect(point.x - pix2_5, point.y - pix2_5, point.x + pix2_5, point.y + pix2_5);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			tglFillRect(point.x - pix2, point.y - pix2, point.x + pix2, point.y + pix2);
Toshihiro Shimizu 890ddd
			if (!m_selection.isSelected(i)) {
Toshihiro Shimizu 890ddd
				tglColor(color2);
Toshihiro Shimizu 890ddd
				tglFillRect(point.x - pix, point.y - pix, point.x + pix, point.y + pix);
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 ControlPointEditorTool::draw()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi(getImage(false));
Toshihiro Shimizu 890ddd
	if (!m_draw)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int currentStroke = m_controlPointEditorStroke.getStrokeIndex();
Toshihiro Shimizu 890ddd
	if (!vi || currentStroke == -1 || m_controlPointEditorStroke.getControlPointCount() == 0 ||
Toshihiro Shimizu 890ddd
		vi->getStrokeCount() == 0 || (int)vi->getStrokeCount() <= currentStroke) {
Toshihiro Shimizu 890ddd
		m_controlPointEditorStroke.setStroke((TVectorImage *)0, -1);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPixel color1, color2;
Toshihiro Shimizu 890ddd
	if (m_action == RECT_SELECTION) //Disegna il rettangolo per la selezione
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		color1 = TPixel32::Black; //TransparencyCheck::instance()->isEnabled()?TPixel32::White:TPixel32::Black;
Toshihiro Shimizu 890ddd
		drawRect(m_selectingRect, color1, 0x3F33, true);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_controlPointEditorStroke.getControlPointCount() <= 0)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	color1 = TPixel(79, 128, 255);
Toshihiro Shimizu 890ddd
	color2 = TPixel::White;
Toshihiro Shimizu 890ddd
	TStroke *stroke = m_controlPointEditorStroke.getStroke();
Toshihiro Shimizu 890ddd
	tglColor(color1);
Toshihiro Shimizu 890ddd
	drawStrokeCenterline(*stroke, getPixelSize());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	drawControlPoint();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	drawMovingSegment();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::mouseMove(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Scelgo il cursore in base alla distanza del mouse dalla curva e dai punti di controllo
Toshihiro Shimizu 890ddd
	TVectorImageP vi(getImage(false));
Toshihiro Shimizu 890ddd
	if (!vi) {
Toshihiro Shimizu 890ddd
		m_controlPointEditorStroke.setStroke((TVectorImage *)0, -1);
Toshihiro Shimizu 890ddd
		m_cursorType = NO_ACTIVE;
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		m_cursorType = NORMAL;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_pos = pos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_draw || m_controlPointEditorStroke.getStrokeIndex() == -1)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	if (e.isAltPressed())
Toshihiro Shimizu 890ddd
		m_cursorType = EDIT_SPEED;
Toshihiro Shimizu 890ddd
	else {
Toshihiro Shimizu 890ddd
		double maxDist = 5 * getPixelSize();
Toshihiro Shimizu 890ddd
		double maxDist2 = maxDist * maxDist;
Toshihiro Shimizu 890ddd
		int pointIndexCP;
Toshihiro Shimizu 890ddd
		ControlPointEditorStroke::PointType pointType = m_controlPointEditorStroke.getPointTypeAt(pos, maxDist2, pointIndexCP);
Toshihiro Shimizu 890ddd
		if (pointType == ControlPointEditorStroke::SEGMENT && e.isCtrlPressed())
Toshihiro Shimizu 890ddd
			m_cursorType = ADD;
Toshihiro Shimizu 890ddd
		//else if(pointType == ControlPointEditorStroke::SEGMENT)
Toshihiro Shimizu 890ddd
		//m_cursorType=EDIT_SEGMENT;
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			m_cursorType = NORMAL;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_pos = pos;
Toshihiro Shimizu 890ddd
	double maxDist = 5 * getPixelSize();
Toshihiro Shimizu 890ddd
	double maxDist2 = maxDist * maxDist;
Toshihiro Shimizu 890ddd
	double dist2 = 0;
Toshihiro Shimizu 890ddd
	int pointIndex;
Toshihiro Shimizu 890ddd
	ControlPointEditorStroke::PointType pointType = m_controlPointEditorStroke.getPointTypeAt(pos, maxDist2, pointIndex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (pointType == ControlPointEditorStroke::NONE) {
Toshihiro Shimizu 890ddd
		// ho cliccato lontano dalla curva corrente
Toshihiro Shimizu 890ddd
		TTool::Application *app = TTool::getApplication();
Toshihiro Shimizu 890ddd
		if (m_autoSelectDrawing.getValue()) {
Toshihiro Shimizu 890ddd
			//Non sono in nessun gadget
Toshihiro Shimizu 890ddd
			std::vector<int> columnIndexes;</int>
Toshihiro Shimizu 890ddd
			getViewer()->posToColumnIndexes(e.m_pos, columnIndexes, getPixelSize() * 5, false);
Toshihiro Shimizu 890ddd
			getNearestStrokeColumnIndexes(columnIndexes, pos);
Toshihiro Shimizu 890ddd
			if (!columnIndexes.empty()) {
Toshihiro Shimizu 890ddd
				int currentColumnIndex = app->getCurrentColumn()->getColumnIndex();
Toshihiro Shimizu 890ddd
				int columnIndex;
Toshihiro Shimizu 890ddd
				if (columnIndexes.size() == 1)
Toshihiro Shimizu 890ddd
					columnIndex = columnIndexes[0];
Toshihiro Shimizu 890ddd
				else {
Toshihiro Shimizu 890ddd
					ToolUtils::ColumChooserMenu *menu = new ToolUtils::ColumChooserMenu(app->getCurrentXsheet()->getXsheet(), columnIndexes);
Toshihiro Shimizu 890ddd
					m_isMenuViewed = true;
Toshihiro Shimizu 890ddd
					columnIndex = menu->execute();
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				TXshColumn *column = app->getCurrentXsheet()->getXsheet()->getColumn(columnIndex);
Toshihiro Shimizu 890ddd
				if (columnIndex >= 0 && columnIndex != currentColumnIndex && column && !column->isLocked()) {
Toshihiro Shimizu 890ddd
					TAffine aff = getMatrix();
Toshihiro Shimizu 890ddd
					app->getCurrentColumn()->setColumnIndex(columnIndex);
Toshihiro Shimizu 890ddd
					updateMatrix();
Toshihiro Shimizu 890ddd
					currentColumnIndex = columnIndex;
Toshihiro Shimizu 890ddd
					m_pos = getMatrix().inv() * aff * pos;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TVectorImageP vi = getImage(false);
Toshihiro Shimizu 890ddd
		if (!vi)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		double dist2, t = 0;
Toshihiro Shimizu 890ddd
		UINT index = -1;
Toshihiro Shimizu 890ddd
		if (vi->getNearestStroke(m_pos, t, index, dist2) && dist2 < 25 * getPixelSize() * getPixelSize()) {
Toshihiro Shimizu 890ddd
			// ho cliccato vicino alla curva index-esima
Toshihiro Shimizu 890ddd
			assert(0 <= index && index < vi->getStrokeCount());
Toshihiro Shimizu 890ddd
			m_controlPointEditorStroke.setStroke(vi, index);
Toshihiro Shimizu 890ddd
			m_action = NONE;
Toshihiro Shimizu 890ddd
			m_selection.makeCurrent();
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			// ho cliccato lontano da ogni altra curva
Toshihiro Shimizu 890ddd
			m_selectingRect = TRectD(m_pos.x, m_pos.y, m_pos.x + 1, m_pos.y + 1);
Toshihiro Shimizu 890ddd
			if (m_selectingRect.x0 > m_selectingRect.x1)
Toshihiro Shimizu 890ddd
				tswap(m_selectingRect.x1, m_selectingRect.x0);
Toshihiro Shimizu 890ddd
			if (m_selectingRect.y0 > m_selectingRect.y1)
Toshihiro Shimizu 890ddd
				tswap(m_selectingRect.y1, m_selectingRect.y0);
Toshihiro Shimizu 890ddd
			m_action = RECT_SELECTION;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		m_selection.selectNone();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TVectorImageP vi = getImage(true);
Toshihiro Shimizu 890ddd
	if (!vi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (pointType == ControlPointEditorStroke::SPEED_IN || pointType == ControlPointEditorStroke::SPEED_OUT) {
Toshihiro Shimizu 890ddd
		bool isIn = pointType == ControlPointEditorStroke::SPEED_IN;
Toshihiro Shimizu 890ddd
		m_selection.selectNone();
Toshihiro Shimizu 890ddd
		m_selection.select(pointIndex);
Toshihiro Shimizu 890ddd
		m_action = isIn ? IN_SPEED_MOVEMENT : OUT_SPEED_MOVEMENT;
Toshihiro Shimizu 890ddd
		if (e.isAltPressed()) {
Toshihiro Shimizu 890ddd
			initUndo();
Toshihiro Shimizu 890ddd
			if (m_controlPointEditorStroke.isCusp(pointIndex))
Toshihiro Shimizu 890ddd
				linkSpeedInOut(pointIndex);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				unlinkSpeedInOut(pointIndex);
Toshihiro Shimizu 890ddd
			TUndoManager::manager()->add(m_undo);
Toshihiro Shimizu 890ddd
			m_undo = 0;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		m_selection.makeCurrent();
Toshihiro Shimizu 890ddd
	} else if (pointType == ControlPointEditorStroke::CONTROL_POINT) {
Toshihiro Shimizu 890ddd
		if (e.isAltPressed()) {
Toshihiro Shimizu 890ddd
			m_selection.selectNone();
Toshihiro Shimizu 890ddd
			m_selection.select(pointIndex);
Toshihiro Shimizu 890ddd
			initUndo();
Toshihiro Shimizu 890ddd
			bool isSpeedIn = m_controlPointEditorStroke.isSpeedInLinear(pointIndex);
Toshihiro Shimizu 890ddd
			bool isSpeedOut = m_controlPointEditorStroke.isSpeedOutLinear(pointIndex);
Toshihiro Shimizu 890ddd
			m_controlPointEditorStroke.setLinear(pointIndex, !isSpeedIn && !isSpeedOut);
Toshihiro Shimizu 890ddd
			TUndoManager::manager()->add(m_undo);
Toshihiro Shimizu 890ddd
			m_undo = 0;
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (e.isCtrlPressed()) {
Toshihiro Shimizu 890ddd
			if (m_selection.isSelected(pointIndex))
Toshihiro Shimizu 890ddd
				m_selection.unselect(pointIndex);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				m_selection.select(pointIndex);
Toshihiro Shimizu 890ddd
		} else if (m_selection.isEmpty() || !m_selection.isSelected(pointIndex)) {
Toshihiro Shimizu 890ddd
			m_selection.selectNone();
Toshihiro Shimizu 890ddd
			m_selection.select(pointIndex);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		m_lastPointSelected = pointIndex;
Toshihiro Shimizu 890ddd
		m_action = CP_MOVEMENT;
Toshihiro Shimizu 890ddd
		m_selection.makeCurrent();
Toshihiro Shimizu 890ddd
	} else if (pointType == ControlPointEditorStroke::SEGMENT && !e.isAltPressed()) {
Toshihiro Shimizu 890ddd
		m_selection.selectNone();
Toshihiro Shimizu 890ddd
		if (e.isCtrlPressed()) {
Toshihiro Shimizu 890ddd
			//Aggiungo un punto
Toshihiro Shimizu 890ddd
			initUndo();
Toshihiro Shimizu 890ddd
			pointIndex = m_controlPointEditorStroke.addControlPoint(pos);
Toshihiro Shimizu 890ddd
			m_selection.select(pointIndex);
Toshihiro Shimizu 890ddd
			m_action = CP_MOVEMENT;
Toshihiro Shimizu 890ddd
			TUndoManager::manager()->add(m_undo);
Toshihiro Shimizu 890ddd
			m_lastPointSelected = -1;
Toshihiro Shimizu 890ddd
			notifyImageChanged();
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			//Inizio a muovere la curva
Toshihiro Shimizu 890ddd
			int precPointIndex, nextPointIndex;
Toshihiro Shimizu 890ddd
			precPointIndex = pointIndex;
Toshihiro Shimizu 890ddd
			nextPointIndex = (m_controlPointEditorStroke.isSelfLoop() &&
Toshihiro Shimizu 890ddd
							  precPointIndex == m_controlPointEditorStroke.getControlPointCount() - 1)
Toshihiro Shimizu 890ddd
								 ? 0
Toshihiro Shimizu 890ddd
								 : precPointIndex + 1;
Toshihiro Shimizu 890ddd
			if (precPointIndex > -1 && nextPointIndex > -1) {
Toshihiro Shimizu 890ddd
				if (precPointIndex > nextPointIndex)
Toshihiro Shimizu 890ddd
					tswap(precPointIndex, nextPointIndex);
Toshihiro Shimizu 890ddd
				m_moveSegmentLimitation.first = precPointIndex;
Toshihiro Shimizu 890ddd
				m_moveSegmentLimitation.second = nextPointIndex;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			m_moveControlPointEditorStroke = *m_controlPointEditorStroke.clone();
Toshihiro Shimizu 890ddd
			//Se e' premuto shift setto a cusp i due punti di controllo che delimitano il segmento.
Toshihiro Shimizu 890ddd
			if (e.isShiftPressed()) {
Toshihiro Shimizu 890ddd
				if (!m_controlPointEditorStroke.isCusp(precPointIndex)) {
Toshihiro Shimizu 890ddd
					m_controlPointEditorStroke.setCusp(precPointIndex, true, false);
Toshihiro Shimizu 890ddd
					m_moveControlPointEditorStroke.setCusp(precPointIndex, true, false);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				if (!m_controlPointEditorStroke.isCusp(nextPointIndex)) {
Toshihiro Shimizu 890ddd
					m_controlPointEditorStroke.setCusp(nextPointIndex, true, true);
Toshihiro Shimizu 890ddd
					m_moveControlPointEditorStroke.setCusp(nextPointIndex, true, true);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			m_action = SEGMENT_MOVEMENT;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		m_selection.makeCurrent();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int currentStroke = m_controlPointEditorStroke.getStrokeIndex();
Toshihiro Shimizu 890ddd
	if (currentStroke != -1)
Toshihiro Shimizu 890ddd
		initUndo();
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
	m_isImageChanged = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::rightButtonDown(const TPointD &pos, const TMouseEvent &)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi = getImage(true);
Toshihiro Shimizu 890ddd
	if (!vi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	double maxDist = 5 * getPixelSize();
Toshihiro Shimizu 890ddd
	double maxDist2 = maxDist * maxDist;
Toshihiro Shimizu 890ddd
	double dist2 = 0;
Toshihiro Shimizu 890ddd
	int pointIndex;
Toshihiro Shimizu 890ddd
	ControlPointEditorStroke::PointType pointType = m_controlPointEditorStroke.getPointTypeAt(pos, maxDist2, pointIndex);
Toshihiro Shimizu 890ddd
	if (pointType != ControlPointEditorStroke::CONTROL_POINT)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	m_selection.select(pointIndex);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::moveControlPoints(const TPointD &delta)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	int cpCount = m_controlPointEditorStroke.getControlPointCount();
Toshihiro Shimizu 890ddd
	for (i = 0; i < cpCount; i++)
Toshihiro Shimizu 890ddd
		if (m_selection.isSelected(i))
Toshihiro Shimizu 890ddd
			m_controlPointEditorStroke.moveControlPoint(i, delta);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::moveSpeed(const TPointD &delta, bool isIn)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < m_controlPointEditorStroke.getControlPointCount(); i++)
Toshihiro Shimizu 890ddd
		if (m_selection.isSelected(i))
Toshihiro Shimizu 890ddd
			m_controlPointEditorStroke.moveSpeed(i, delta, isIn, 4 * getPixelSize());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::moveSegment(const TPointD &delta, bool dragging, bool isShiftPressed)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int beforeIndex = m_moveSegmentLimitation.first;
Toshihiro Shimizu 890ddd
	int nextIndex = m_moveSegmentLimitation.second;
Toshihiro Shimizu 890ddd
	//Se e' premuto shift setto a cusp i due punti di controllo che delimitano il segmento.
Toshihiro Shimizu 890ddd
	if (isShiftPressed) {
Toshihiro Shimizu 890ddd
		if (!m_controlPointEditorStroke.isCusp(beforeIndex)) {
Toshihiro Shimizu 890ddd
			if (dragging)
Toshihiro Shimizu 890ddd
				m_moveControlPointEditorStroke.setCusp(beforeIndex, true, false);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				m_controlPointEditorStroke.setCusp(beforeIndex, true, false);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (!m_controlPointEditorStroke.isCusp(nextIndex)) {
Toshihiro Shimizu 890ddd
			if (dragging)
Toshihiro Shimizu 890ddd
				m_moveControlPointEditorStroke.setCusp(nextIndex, true, true);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				m_controlPointEditorStroke.setCusp(nextIndex, true, true);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (dragging)
Toshihiro Shimizu 890ddd
		m_moveControlPointEditorStroke.moveSegment(beforeIndex, nextIndex, delta, m_pos);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		m_controlPointEditorStroke.moveSegment(beforeIndex, nextIndex, delta, m_pos);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi(getImage(true));
Toshihiro Shimizu 890ddd
	int currentStroke = m_controlPointEditorStroke.getStrokeIndex();
Toshihiro Shimizu 890ddd
	if (!vi || currentStroke == -1 || m_action == NONE)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	QMutexLocker lock(vi->getMutex());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD delta = pos - m_pos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_action == CP_MOVEMENT) {
Toshihiro Shimizu 890ddd
		m_pos = pos;
Toshihiro Shimizu 890ddd
		if (!m_selection.isSelected(m_lastPointSelected) && e.isCtrlPressed())
Toshihiro Shimizu 890ddd
			m_selection.select(m_lastPointSelected); // Controllo che non venga deselezionata l'ultima selezione nel movimento
Toshihiro Shimizu 890ddd
		moveControlPoints(delta);
Toshihiro Shimizu 890ddd
		m_isImageChanged = true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (m_action == SEGMENT_MOVEMENT) {
Toshihiro Shimizu 890ddd
		m_moveControlPointEditorStroke = *m_controlPointEditorStroke.clone();
Toshihiro Shimizu 890ddd
		moveSegment(delta, true, e.isShiftPressed());
Toshihiro Shimizu 890ddd
		m_isImageChanged = true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (m_action == OUT_SPEED_MOVEMENT || m_action == IN_SPEED_MOVEMENT) {
Toshihiro Shimizu 890ddd
		m_pos = pos;
Toshihiro Shimizu 890ddd
		moveSpeed(delta, m_action == IN_SPEED_MOVEMENT);
Toshihiro Shimizu 890ddd
		m_isImageChanged = true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_action == RECT_SELECTION) {
Toshihiro Shimizu 890ddd
		int cpCount = m_controlPointEditorStroke.getControlPointCount();
Toshihiro Shimizu 890ddd
		m_selectingRect.x0 = m_pos.x;
Toshihiro Shimizu 890ddd
		m_selectingRect.y0 = m_pos.y;
Toshihiro Shimizu 890ddd
		m_selectingRect.x1 = pos.x;
Toshihiro Shimizu 890ddd
		m_selectingRect.y1 = pos.y;
Toshihiro Shimizu 890ddd
		if (m_selectingRect.x0 > m_selectingRect.x1)
Toshihiro Shimizu 890ddd
			tswap(m_selectingRect.x1, m_selectingRect.x0);
Toshihiro Shimizu 890ddd
		if (m_selectingRect.y0 > m_selectingRect.y1)
Toshihiro Shimizu 890ddd
			tswap(m_selectingRect.y1, m_selectingRect.y0);
Toshihiro Shimizu 890ddd
		int i;
Toshihiro Shimizu 890ddd
		m_selection.selectNone();
Toshihiro Shimizu 890ddd
		for (i = 0; i < cpCount; i++)
Toshihiro Shimizu 890ddd
			if (m_selectingRect.contains(m_controlPointEditorStroke.getControlPoint(i)))
Toshihiro Shimizu 890ddd
				m_selection.select(i);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi(getImage(true));
Toshihiro Shimizu 890ddd
	int currentStroke = m_controlPointEditorStroke.getStrokeIndex();
Toshihiro Shimizu 890ddd
	if (!vi || currentStroke == -1)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	QMutexLocker lock(vi->getMutex());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_action == EDIT_SEGMENT) {
Toshihiro Shimizu 890ddd
		m_moveControlPointEditorStroke.setStroke((TVectorImage *)0, -1);
Toshihiro Shimizu 890ddd
		TPointD delta = pos - m_pos;
Toshihiro Shimizu 890ddd
		moveSegment(delta, false, e.isShiftPressed());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_action == RECT_SELECTION) {
Toshihiro Shimizu 890ddd
		if (m_selection.isEmpty()) {
Toshihiro Shimizu 890ddd
			//Non ho selezionato nulla
Toshihiro Shimizu 890ddd
			if (!TTool::getApplication()->getCurrentObject()->isSpline()) // se non e' una spline deseleziono
Toshihiro Shimizu 890ddd
				m_controlPointEditorStroke.setStroke((TVectorImage *)0, -1);
Toshihiro Shimizu 890ddd
			m_action = NONE;
Toshihiro Shimizu 890ddd
			m_isImageChanged = false;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			m_action = CP_MOVEMENT;
Toshihiro Shimizu 890ddd
			m_selection.makeCurrent();
Toshihiro Shimizu 890ddd
			m_isImageChanged = false;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_action == NONE || !m_isImageChanged) {
Toshihiro Shimizu 890ddd
		m_undo = 0;
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	notifyImageChanged();
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Registro l'UNDO
Toshihiro Shimizu 890ddd
	if (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
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::addContextMenuItems(QMenu *menu)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_isMenuViewed = true;
Toshihiro Shimizu 890ddd
	m_selection.addMenuItems(menu);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::linkSpeedInOut(int index)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if ((index == 0 || index == m_controlPointEditorStroke.getControlPointCount() - 1) && !m_controlPointEditorStroke.isSelfLoop())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	if (m_action == IN_SPEED_MOVEMENT || m_action == CP_MOVEMENT)
Toshihiro Shimizu 890ddd
		m_controlPointEditorStroke.setCusp(index, false, true);
Toshihiro Shimizu 890ddd
	if (m_action == OUT_SPEED_MOVEMENT)
Toshihiro Shimizu 890ddd
		m_controlPointEditorStroke.setCusp(index, false, false);
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::unlinkSpeedInOut(int pointIndex)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_controlPointEditorStroke.setCusp(pointIndex, true, true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ControlPointEditorTool::keyDown(int key, TUINT32 flags, const TPoint &pos)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi(getImage(true));
Toshihiro Shimizu 890ddd
	if (!vi || (vi && m_selection.isEmpty()))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Inizializzo l'UNDO
Toshihiro Shimizu 890ddd
	initUndo();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD delta;
Toshihiro Shimizu 890ddd
	if (key == TwConsts::TK_UpArrow)
Toshihiro Shimizu 890ddd
		delta.y = 1;
Toshihiro Shimizu 890ddd
	else if (key == TwConsts::TK_DownArrow)
Toshihiro Shimizu 890ddd
		delta.y = -1;
Toshihiro Shimizu 890ddd
	else if (key == TwConsts::TK_LeftArrow)
Toshihiro Shimizu 890ddd
		delta.x = -1;
Toshihiro Shimizu 890ddd
	else if (key == TwConsts::TK_RightArrow)
Toshihiro Shimizu 890ddd
		delta.x = 1;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	moveControlPoints(delta);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
	//Registro l'UNDO
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->add(m_undo);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::onEnter()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi(getImage(false));
Toshihiro Shimizu 890ddd
	int currentStroke = m_controlPointEditorStroke.getStrokeIndex();
Toshihiro Shimizu 890ddd
	if (m_isMenuViewed) {
Toshihiro Shimizu 890ddd
		m_isMenuViewed = false;
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	/*m_draw=true;
Toshihiro Shimizu 890ddd
	if(currentStroke==-1 || !vi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_controlPointEditorStroke.setStroke((TVectorImage*)0, -1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  if(TTool::getApplication()->getCurrentObject()->isSpline())
Toshihiro Shimizu 890ddd
		m_controlPointEditorStroke.setStroke(vi, 0);*/
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::onLeave()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_isMenuViewed)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	//m_draw=false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ControlPointEditorTool::onPropertyChanged(string propertyName)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	AutoSelectDrawing = (int)(m_autoSelectDrawing.getValue());
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::onActivate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// TODO: getApplication()->editImageOrSpline();
Toshihiro Shimizu 890ddd
	m_autoSelectDrawing.setValue(AutoSelectDrawing ? 1 : 0);
Toshihiro Shimizu 890ddd
	m_controlPointEditorStroke.setStroke((TVectorImage *)0, -1);
Toshihiro Shimizu 890ddd
	m_draw = true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::onDeactivate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_draw = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ControlPointEditorTool::onImageChanged()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi(getImage(false));
Toshihiro Shimizu 890ddd
	if (!vi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int currentStroke = m_controlPointEditorStroke.getStrokeIndex();
Toshihiro Shimizu 890ddd
	if (!vi || currentStroke == -1 || m_controlPointEditorStroke.getControlPointCount() == 0 ||
Toshihiro Shimizu 890ddd
		vi->getStrokeCount() == 0 || (int)vi->getStrokeCount() <= currentStroke) {
Toshihiro Shimizu 890ddd
		m_controlPointEditorStroke.setStroke((TVectorImage *)0, -1);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		m_selection.selectNone();
Toshihiro Shimizu 890ddd
		m_controlPointEditorStroke.setStroke(vi, currentStroke);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int ControlPointEditorTool::getCursorId() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	switch (m_cursorType) {
Toshihiro Shimizu 890ddd
	case NORMAL:
Toshihiro Shimizu 890ddd
		return ToolCursor::SplineEditorCursor;
Toshihiro Shimizu 890ddd
	case ADD:
Toshihiro Shimizu 890ddd
		return ToolCursor::SplineEditorCursorAdd;
Toshihiro Shimizu 890ddd
	case EDIT_SPEED:
Toshihiro Shimizu 890ddd
		return ToolCursor::SplineEditorCursorSelect;
Toshihiro Shimizu 890ddd
	case EDIT_SEGMENT:
Toshihiro Shimizu 890ddd
		return ToolCursor::PinchCursor;
Toshihiro Shimizu 890ddd
	case NO_ACTIVE:
Toshihiro Shimizu 890ddd
		return ToolCursor::CURSOR_NO;
Toshihiro Shimizu 890ddd
	default:
Toshihiro Shimizu 890ddd
		return ToolCursor::SplineEditorCursor;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//TTool *getSplineEditorTool() {return &controlPointEditorTool;}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================