Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzTools includes
Toshihiro Shimizu 890ddd
#include "tools/toolhandle.h"
Toshihiro Shimizu 890ddd
#include "tools/toolutils.h"
Toshihiro Shimizu 890ddd
#include "tools/tool.h"
Toshihiro Shimizu 890ddd
#include "tools/cursors.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzQt includes
Toshihiro Shimizu 890ddd
#include "toonzqt/imageutils.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/txshlevelhandle.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/strokegenerator.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsimplelevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/stage2.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tenv.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tmathutil.h"
Toshihiro Shimizu 890ddd
#include "tundo.h"
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
#include "tproperty.h"
Toshihiro Shimizu 890ddd
#include "tgl.h"
Toshihiro Shimizu 890ddd
#include "tinbetween.h"
Toshihiro Shimizu 890ddd
#include "drawutil.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qcoreapplication> // For Qt translation support</qcoreapplication>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace ToolUtils;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TEnv::DoubleVar EraseVectorSize("InknpaintEraseVectorSize", 10);
Toshihiro Shimizu 890ddd
TEnv::StringVar EraseVectorType("InknpaintEraseVectorType", "Normal");
Toshihiro Shimizu 890ddd
TEnv::IntVar EraseVectorSelective("InknpaintEraseVectorSelective", 0);
Toshihiro Shimizu 890ddd
TEnv::IntVar EraseVectorInvert("InknpaintEraseVectorInvert", 0);
Toshihiro Shimizu 890ddd
TEnv::IntVar EraseVectorRange("InknpaintEraseVectorRange", 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//Eraser Tool
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define NORMAL_ERASE L"Normal"
Toshihiro Shimizu 890ddd
#define RECT_ERASE L"Rectangular"
Toshihiro Shimizu 890ddd
#define FREEHAND_ERASE L"Freehand"
Toshihiro Shimizu 890ddd
#define POLYLINE_ERASE L"Polyline"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const double minDistance2 = 16.0; //4 pixel
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
void mapToVector(const std::map<int, *="" vistroke=""> &theMap, std::vector<int> &theVect)</int></int,>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(theMap.size() == theVect.size());
Shinya Kitaoka 3bfa54
	std::map<int, *="" vistroke="">::const_iterator it = theMap.begin();</int,>
Toshihiro Shimizu 890ddd
	UINT i = 0;
Toshihiro Shimizu 890ddd
	for (; it != theMap.end(); ++it) {
Toshihiro Shimizu 890ddd
		theVect[i++] = it->first;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class UndoEraser : public ToolUtils::TToolUndo
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 3bfa54
	std::vector<tfilledregioninf> m_oldFillInformation, m_newFillInformation;</tfilledregioninf>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int m_row;
Toshihiro Shimizu 890ddd
	int m_column;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 3bfa54
	std::map<int, *="" vistroke=""> m_originalStrokes;</int,>
Shinya Kitaoka 3bfa54
	std::map<int, *="" vistroke=""> m_newStrokes;</int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UndoEraser(TXshSimpleLevel *level, const TFrameId &frameId)
Toshihiro Shimizu 890ddd
		: ToolUtils::TToolUndo(level, frameId)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TVectorImageP image = level->getFrame(m_frameId, true);
Toshihiro Shimizu 890ddd
		if (!image)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		TTool::Application *app = TTool::getApplication();
Toshihiro Shimizu 890ddd
		if (app) {
Toshihiro Shimizu 890ddd
			m_row = app->getCurrentFrame()->getFrame();
Toshihiro Shimizu 890ddd
			m_column = app->getCurrentColumn()->getColumnIndex();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		ImageUtils::getFillingInformationInArea(image, m_oldFillInformation, image->getBBox());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void onAdd()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TVectorImageP image = m_level->getFrame(m_frameId, true);
Toshihiro Shimizu 890ddd
		assert(!!image);
Toshihiro Shimizu 890ddd
		if (!image)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		ImageUtils::getFillingInformationInArea(image, m_newFillInformation, image->getBBox());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~UndoEraser()
Toshihiro Shimizu 890ddd
	{
Shinya Kitaoka 3bfa54
		std::map<int, *="" vistroke="">::const_iterator it;</int,>
Toshihiro Shimizu 890ddd
		for (it = m_originalStrokes.begin(); it != m_originalStrokes.end(); ++it)
Toshihiro Shimizu 890ddd
			deleteVIStroke(it->second);
Toshihiro Shimizu 890ddd
		for (it = m_newStrokes.begin(); it != m_newStrokes.end(); ++it)
Toshihiro Shimizu 890ddd
			deleteVIStroke(it->second);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void addOldStroke(int index, VIStroke *stroke)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		VIStroke *s = cloneVIStroke(stroke);
Shinya Kitaoka 3bfa54
		m_originalStrokes.insert(std::map<int, *="" vistroke="">::value_type(index, s));</int,>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void addNewStroke(int index, VIStroke *stroke)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		VIStroke *s = cloneVIStroke(stroke);
Shinya Kitaoka 3bfa54
		m_newStrokes.insert(std::map<int, *="" vistroke="">::value_type(index, s));</int,>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void undo() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TTool::Application *app = TTool::getApplication();
Toshihiro Shimizu 890ddd
		if (!app)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TFrameId currentFid;
Toshihiro Shimizu 890ddd
		if (app->getCurrentFrame()->isEditingScene()) {
Toshihiro Shimizu 890ddd
			app->getCurrentColumn()->setColumnIndex(m_column);
Toshihiro Shimizu 890ddd
			app->getCurrentFrame()->setFrame(m_row);
Toshihiro Shimizu 890ddd
			currentFid = TFrameId(m_row + 1);
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			app->getCurrentFrame()->setFid(m_frameId);
Toshihiro Shimizu 890ddd
			currentFid = m_frameId;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TVectorImageP image = m_level->getFrame(m_frameId, true);
Toshihiro Shimizu 890ddd
		assert(image);
Toshihiro Shimizu 890ddd
		if (!image)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		QMutexLocker lock(image->getMutex());
Shinya Kitaoka 3bfa54
		std::vector<int> newStrokeIndex(m_newStrokes.size());</int>
Toshihiro Shimizu 890ddd
		mapToVector(m_newStrokes, newStrokeIndex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		image->removeStrokes(newStrokeIndex, true, false);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
		std::map<int, *="" vistroke="">::const_iterator it = m_originalStrokes.begin();</int,>
Toshihiro Shimizu 890ddd
		UINT i = 0;
Toshihiro Shimizu 890ddd
		VIStroke *s;
Toshihiro Shimizu 890ddd
		for (; it != m_originalStrokes.end(); ++it) {
Toshihiro Shimizu 890ddd
			s = cloneVIStroke(it->second);
Toshihiro Shimizu 890ddd
			image->insertStrokeAt(s, it->first);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (image->isComputedRegionAlmostOnce())
Toshihiro Shimizu 890ddd
			image->findRegions(); //in futuro togliere. Serve perche' la  removeStrokes, se gli si dice
Toshihiro Shimizu 890ddd
		//di non calcolare le regioni, e' piu' veloce ma poi chrash tutto
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		UINT size = m_oldFillInformation.size();
Toshihiro Shimizu 890ddd
		if (!size) {
Toshihiro Shimizu 890ddd
			app->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
			notifyImageChanged();
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TRegion *reg;
Toshihiro Shimizu 890ddd
		i = 0;
Toshihiro Shimizu 890ddd
		for (; i < size; i++) {
Toshihiro Shimizu 890ddd
			reg = image->getRegion(m_oldFillInformation[i].m_regionId);
Toshihiro Shimizu 890ddd
			assert(reg);
Toshihiro Shimizu 890ddd
			if (reg)
Toshihiro Shimizu 890ddd
				reg->setStyle(m_oldFillInformation[i].m_styleId);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		app->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
		notifyImageChanged();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TTool::Application *app = TTool::getApplication();
Toshihiro Shimizu 890ddd
		if (!app)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TFrameId currentFid;
Toshihiro Shimizu 890ddd
		if (app->getCurrentFrame()->isEditingScene()) {
Toshihiro Shimizu 890ddd
			app->getCurrentColumn()->setColumnIndex(m_column);
Toshihiro Shimizu 890ddd
			app->getCurrentFrame()->setFrame(m_row);
Toshihiro Shimizu 890ddd
			currentFid = TFrameId(m_row + 1);
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			app->getCurrentFrame()->setFid(m_frameId);
Toshihiro Shimizu 890ddd
			currentFid = m_frameId;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		TVectorImageP image = m_level->getFrame(m_frameId, true);
Toshihiro Shimizu 890ddd
		assert(image);
Toshihiro Shimizu 890ddd
		if (!image)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		QMutexLocker lock(image->getMutex());
Shinya Kitaoka 3bfa54
		std::vector<int> oldStrokeIndex(m_originalStrokes.size());</int>
Toshihiro Shimizu 890ddd
		mapToVector(m_originalStrokes, oldStrokeIndex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		image->removeStrokes(oldStrokeIndex, true, false);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
		std::map<int, *="" vistroke="">::const_iterator it = m_newStrokes.begin();</int,>
Toshihiro Shimizu 890ddd
		UINT i = 0;
Toshihiro Shimizu 890ddd
		VIStroke *s;
Toshihiro Shimizu 890ddd
		for (; it != m_newStrokes.end(); ++it) {
Toshihiro Shimizu 890ddd
			s = cloneVIStroke(it->second);
Toshihiro Shimizu 890ddd
			image->insertStrokeAt(s, it->first);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (image->isComputedRegionAlmostOnce())
Toshihiro Shimizu 890ddd
			image->findRegions(); //in futuro togliere. Serve perche' la  removeStrokes, se gli si dice
Toshihiro Shimizu 890ddd
		//di non calcolare le regioni, e' piu' veloce ma poi chrash tutto
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		UINT size = m_newFillInformation.size();
Toshihiro Shimizu 890ddd
		if (!size) {
Toshihiro Shimizu 890ddd
			app->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
			notifyImageChanged();
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TRegion *reg;
Toshihiro Shimizu 890ddd
		i = 0;
Toshihiro Shimizu 890ddd
		for (; i < size; i++) {
Toshihiro Shimizu 890ddd
			reg = image->getRegion(m_newFillInformation[i].m_regionId);
Toshihiro Shimizu 890ddd
			assert(reg);
Toshihiro Shimizu 890ddd
			if (reg)
Toshihiro Shimizu 890ddd
				reg->setStyle(m_newFillInformation[i].m_styleId);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		app->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
		notifyImageChanged();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return sizeof(*this) + (m_oldFillInformation.capacity() + m_newFillInformation.capacity()) * sizeof(TFilledRegionInf) + 500;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString getToolName()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return QString("Vector Eraser Tool");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getHistoryType()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return HistoryType::EraserTool;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//  EraserTool class declaration
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class EraserTool : public TTool
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	Q_DECLARE_TR_FUNCTIONS(EraserTool)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	EraserTool();
Toshihiro Shimizu 890ddd
	~EraserTool();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ToolType getToolType() const { return TTool::LevelWriteTool; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void draw();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void startErase(TVectorImageP vi, const TPointD &pos); //, const TImageLocation &imageLocation);
Toshihiro Shimizu 890ddd
	void erase(TVectorImageP vi, const TPointD &pos);
Toshihiro Shimizu 890ddd
	void erase(TVectorImageP vi, TRectD &rect); //, const TImageLocation &imageLocation);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void stopErase(TVectorImageP vi);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void leftButtonDown(const TPointD &pos, const TMouseEvent &e);
Toshihiro Shimizu 890ddd
	void leftButtonDrag(const TPointD &pos, const TMouseEvent &e);
Toshihiro Shimizu 890ddd
	void leftButtonUp(const TPointD &pos, const TMouseEvent &);
Toshihiro Shimizu 890ddd
	void leftButtonDoubleClick(const TPointD &pos, const TMouseEvent &e);
Toshihiro Shimizu 890ddd
	void mouseMove(const TPointD &pos, const TMouseEvent &e);
Shinya Kitaoka 3bfa54
	bool onPropertyChanged(std::string propertyName);
Toshihiro Shimizu 890ddd
	void onEnter();
Toshihiro Shimizu 890ddd
	void onLeave();
Toshihiro Shimizu 890ddd
	void onActivate();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPropertyGroup *getProperties(int targetType) { return &m_prop; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getCursorId() const { return ToolCursor::EraserCursor; }
Toshihiro Shimizu 890ddd
	void onImageChanged();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*-- ドラッグ中にツールが切り替わった場合、Eraseの終了処理を行う --*/
Toshihiro Shimizu 890ddd
	void onDeactivate();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	TPropertyGroup m_prop;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TEnumProperty m_eraseType;
Toshihiro Shimizu 890ddd
	TDoubleProperty m_toolSize;
Toshihiro Shimizu 890ddd
	TBoolProperty m_selective;
Toshihiro Shimizu 890ddd
	TBoolProperty m_invertOption;
Toshihiro Shimizu 890ddd
	TBoolProperty m_multi;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double m_pointSize,
Toshihiro Shimizu 890ddd
		m_distance2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD m_mousePos, //!< Current mouse position.
Toshihiro Shimizu 890ddd
		m_oldMousePos,  //!< Previous mouse position.
Toshihiro Shimizu 890ddd
		m_brushPos,		//!< Position the brush will be painted at.
Toshihiro Shimizu 890ddd
		m_firstPos;		//!< Either The first point inserted either in m_track or m_polyline
Toshihiro Shimizu 890ddd
						//!  (depending on selected erase mode).
Toshihiro Shimizu 890ddd
	UndoEraser *m_undo;
Shinya Kitaoka 3bfa54
	std::vector<int> m_indexes;</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD m_selectingRect,
Toshihiro Shimizu 890ddd
		m_firstRect;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFrameId m_firstFrameId,
Toshihiro Shimizu 890ddd
		m_veryFirstFrameId;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXshSimpleLevelP m_level;
Toshihiro Shimizu 890ddd
	std::pair<int, int=""> m_currCell;</int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	StrokeGenerator m_track; //!< Lazo selection generator.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::vector<tpointd> m_polyline; //!< Polyline points.</tpointd>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TStroke *m_stroke;		//!< Stores the stroke generated by m_track.
Toshihiro Shimizu 890ddd
	TStroke *m_firstStroke; //!< Stores the first stroke in the "frame range" case.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double m_thick;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool m_firstTime,
Toshihiro Shimizu 890ddd
		m_active,
Toshihiro Shimizu 890ddd
		m_firstFrameSelected;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void resetMulti();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void updateTranslation();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Metodi per disegnare la linea della modalita' Freehand
Toshihiro Shimizu 890ddd
	void startFreehand(const TPointD &pos);
Toshihiro Shimizu 890ddd
	void freehandDrag(const TPointD &pos);
Toshihiro Shimizu 890ddd
	void closeFreehand(const TPointD &pos);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Metodi per disegnare la linea della modalita' Polyline
Toshihiro Shimizu 890ddd
	void addPointPolyline(const TPointD &pos);
Toshihiro Shimizu 890ddd
	void closePolyline(const TPointD &pos);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void eraseRegion(const TVectorImageP vi, TStroke *stroke);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void multiEraseRect(TFrameId firstFrameId, TFrameId lastFrameId,
Toshihiro Shimizu 890ddd
						TRectD firstRect, TRectD lastRect, bool invert);
Toshihiro Shimizu 890ddd
	void doMultiErase(TFrameId &firstFrameId, TFrameId &lastFrameId,
Toshihiro Shimizu 890ddd
					  const TStroke *firstStroke, const TStroke *lastStroke);
Toshihiro Shimizu 890ddd
	void doErase(double t, const TXshSimpleLevelP &sl, const TFrameId &fid,
Toshihiro Shimizu 890ddd
				 const TVectorImageP &firstImage, const TVectorImageP &lastImage);
Toshihiro Shimizu 890ddd
	void multiEreserRegion(TStroke *stroke, const TMouseEvent &e);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} eraserTool;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//  EraserTool implemention
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
EraserTool::EraserTool()
Toshihiro Shimizu 890ddd
	: TTool("T_Eraser"), m_eraseType("Type:") // "W_ToolOptions_Erasetype"
Toshihiro Shimizu 890ddd
	  ,
Toshihiro Shimizu 890ddd
	  m_toolSize("Size:", 1, 100, 10) // "W_ToolOptions_EraserToolSize"
Toshihiro Shimizu 890ddd
	  ,
Toshihiro Shimizu 890ddd
	  m_selective("Selective", false) // "W_ToolOptions_Selective"
Toshihiro Shimizu 890ddd
	  ,
Toshihiro Shimizu 890ddd
	  m_invertOption("Invert", false) // "W_ToolOptions_Invert"
Toshihiro Shimizu 890ddd
	  ,
Toshihiro Shimizu 890ddd
	  m_multi("Frame Range", false) // "W_ToolOptions_FrameRange"
Toshihiro Shimizu 890ddd
	  ,
Toshihiro Shimizu 890ddd
	  m_pointSize(-1), m_undo(0), m_currCell(-1, -1), m_stroke(0), m_thick(5), m_active(false), m_firstTime(true)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	bind(TTool::VectorImage);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_prop.bind(m_toolSize);
Toshihiro Shimizu 890ddd
	m_prop.bind(m_eraseType);
Toshihiro Shimizu 890ddd
	m_eraseType.addValue(NORMAL_ERASE);
Toshihiro Shimizu 890ddd
	m_eraseType.addValue(RECT_ERASE);
Toshihiro Shimizu 890ddd
	m_eraseType.addValue(FREEHAND_ERASE);
Toshihiro Shimizu 890ddd
	m_eraseType.addValue(POLYLINE_ERASE);
Toshihiro Shimizu 890ddd
	m_prop.bind(m_selective);
Toshihiro Shimizu 890ddd
	m_prop.bind(m_invertOption);
Toshihiro Shimizu 890ddd
	m_prop.bind(m_multi);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_selective.setId("Selective");
Toshihiro Shimizu 890ddd
	m_invertOption.setId("Invert");
Toshihiro Shimizu 890ddd
	m_multi.setId("FrameRange");
Toshihiro Shimizu 890ddd
	m_eraseType.setId("Type");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
EraserTool::~EraserTool()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_stroke)
Toshihiro Shimizu 890ddd
		delete m_stroke;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_firstStroke)
Toshihiro Shimizu 890ddd
		delete m_firstStroke;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::updateTranslation()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_toolSize.setQStringName(tr("Size:"));
Toshihiro Shimizu 890ddd
	m_selective.setQStringName(tr("Selective"));
Toshihiro Shimizu 890ddd
	m_invertOption.setQStringName(tr("Invert"));
Toshihiro Shimizu 890ddd
	m_multi.setQStringName(tr("Frame Range"));
Toshihiro Shimizu 890ddd
	m_eraseType.setQStringName(tr("Type:"));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::draw()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_pointSize <= 0)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double pixelSize2 = getPixelSize() * getPixelSize();
Toshihiro Shimizu 890ddd
	m_thick = pixelSize2 / 2.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TImageP image(getImage(false));
Toshihiro Shimizu 890ddd
	TVectorImageP vi = image;
Toshihiro Shimizu 890ddd
	if (vi) {
Toshihiro Shimizu 890ddd
		bool blackBg = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg;
Toshihiro Shimizu 890ddd
		if (m_eraseType.getValue() == RECT_ERASE) {
Toshihiro Shimizu 890ddd
			TPixel color = blackBg ? TPixel32::White : TPixel32::Black;
Toshihiro Shimizu 890ddd
			if (m_multi.getValue() && m_firstFrameSelected)
Toshihiro Shimizu 890ddd
				drawRect(m_firstRect, color, 0x3F33, true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (m_active || (m_multi.getValue() && !m_firstFrameSelected))
Toshihiro Shimizu 890ddd
				drawRect(m_selectingRect, color, 0x3F33, true);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (m_eraseType.getValue() == NORMAL_ERASE) {
Toshihiro Shimizu 890ddd
			tglColor(TPixel32(255, 0, 255));
Toshihiro Shimizu 890ddd
			tglDrawCircle(m_brushPos, m_pointSize);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if ((m_eraseType.getValue() == FREEHAND_ERASE || m_eraseType.getValue() == POLYLINE_ERASE) && m_multi.getValue()) {
Toshihiro Shimizu 890ddd
			TPixel color = blackBg ? TPixel32::White : TPixel32::Black;
Toshihiro Shimizu 890ddd
			tglColor(color);
Toshihiro Shimizu 890ddd
			if (m_firstStroke)
Toshihiro Shimizu 890ddd
				drawStrokeCenterline(*m_firstStroke, 1);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (m_eraseType.getValue() == POLYLINE_ERASE && !m_polyline.empty()) {
Toshihiro Shimizu 890ddd
			TPixel color = blackBg ? TPixel32::White : TPixel32::Black;
Toshihiro Shimizu 890ddd
			tglColor(color);
Toshihiro Shimizu 890ddd
			tglDrawCircle(m_polyline[0], 2);
Toshihiro Shimizu 890ddd
			glBegin(GL_LINE_STRIP);
Toshihiro Shimizu 890ddd
			for (UINT i = 0; i < m_polyline.size(); i++)
Toshihiro Shimizu 890ddd
				tglVertex(m_polyline[i]);
Toshihiro Shimizu 890ddd
			tglVertex(m_mousePos);
Toshihiro Shimizu 890ddd
			glEnd();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::resetMulti()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_firstFrameSelected = false;
Toshihiro Shimizu 890ddd
	m_firstRect.empty();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_selectingRect.empty();
Toshihiro Shimizu 890ddd
	TTool::Application *application = TTool::getApplication();
Toshihiro Shimizu 890ddd
	if (!application)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_firstFrameId = m_veryFirstFrameId = getCurrentFid();
Toshihiro Shimizu 890ddd
	m_level = application->getCurrentLevel()->getLevel()
Toshihiro Shimizu 890ddd
				  ? application->getCurrentLevel()->getLevel()->getSimpleLevel()
Toshihiro Shimizu 890ddd
				  : 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_firstStroke) {
Toshihiro Shimizu 890ddd
		delete m_firstStroke;
Toshihiro Shimizu 890ddd
		m_firstStroke = 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::startErase(TVectorImageP vi, const TPointD &pos) //, const TImageLocation &imageLocation)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	UINT size = vi->getStrokeCount();
Toshihiro Shimizu 890ddd
	m_indexes.resize(size);
Toshihiro Shimizu 890ddd
	for (UINT i = 0; i < size; i++)
Toshihiro Shimizu 890ddd
		m_indexes[i] = i;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(m_undo == 0);
Toshihiro Shimizu 890ddd
	delete m_undo;
Toshihiro Shimizu 890ddd
	TXshSimpleLevel *level = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
	m_undo = new UndoEraser(level, getCurrentFid());
Toshihiro Shimizu 890ddd
	m_oldMousePos = pos;
Toshihiro Shimizu 890ddd
	m_distance2 = minDistance2 * getPixelSize() * getPixelSize();
Toshihiro Shimizu 890ddd
	erase(vi, pos);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::erase(TVectorImageP vi, const TPointD &pos)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::vector<int>::iterator it = m_indexes.begin();</int>
Toshihiro Shimizu 890ddd
	m_distance2 += tdistance2(m_oldMousePos, pos);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_distance2 < minDistance2 * getPixelSize() * getPixelSize())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_distance2 = 0;
Toshihiro Shimizu 890ddd
	m_oldMousePos = pos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//quadrato circoscritto alla circonferenza
Toshihiro Shimizu 890ddd
	TRectD circumscribedSquare(pos.x - m_pointSize, pos.y - m_pointSize, pos.x + m_pointSize, pos.y + m_pointSize);
Toshihiro Shimizu 890ddd
	if (!circumscribedSquare.overlaps(vi->getBBox())) {
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::vector<double> intersections;</double>
Shinya Kitaoka 3bfa54
	std::vector<doublepair> sortedWRanges;</doublepair>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::vector<tstroke *=""> splitStrokes;</tstroke>
Toshihiro Shimizu 890ddd
	double rectEdge_2 = m_pointSize * TConsts::sqrt2_2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//quadrato iscritto nella circonferenza
Toshihiro Shimizu 890ddd
	TRectD enrolledSquare(pos.x - rectEdge_2, pos.y - rectEdge_2, pos.x + rectEdge_2, pos.y + rectEdge_2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT i = 0;
Toshihiro Shimizu 890ddd
	double pointSize2 = sq(m_pointSize);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::vector<int> oneStrokeIndex(1);</int>
Toshihiro Shimizu 890ddd
	int index = TTool::getApplication()->getCurrentLevelStyleIndex();
Toshihiro Shimizu 890ddd
	QMutexLocker lock(vi->getMutex());
Toshihiro Shimizu 890ddd
	while (i < vi->getStrokeCount()) {
Toshihiro Shimizu 890ddd
		assert(it != m_indexes.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TStroke *oldStroke = vi->getStroke(i);
Toshihiro Shimizu 890ddd
		if (!vi->inCurrentGroup(i) || (m_selective.getValue() && oldStroke->getStyle() != index)) {
Toshihiro Shimizu 890ddd
			i++;
Toshihiro Shimizu 890ddd
			it++;
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TRectD strokeBBox = oldStroke->getBBox();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!circumscribedSquare.overlaps(strokeBBox)) { //stroke all'esterno del quadrato circoscritto alla circonferenxa
Toshihiro Shimizu 890ddd
			i++;
Toshihiro Shimizu 890ddd
			it++;
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (enrolledSquare.contains(strokeBBox)) { //stroke tutta contenuta nel quadrato iscritto nella circonferenza
Toshihiro Shimizu 890ddd
			if (*it != -1)
Toshihiro Shimizu 890ddd
				m_undo->addOldStroke(*it, vi->getVIStroke(i));
Toshihiro Shimizu 890ddd
			oneStrokeIndex[0] = i;
Toshihiro Shimizu 890ddd
			vi->removeStrokes(oneStrokeIndex, true, true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			it = m_indexes.erase(it);
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		splitStrokes.clear();
Toshihiro Shimizu 890ddd
		intersections.clear();
Toshihiro Shimizu 890ddd
		/*int intersNum=*/intersect(*oldStroke, pos, m_pointSize, intersections);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		/*
Toshihiro Shimizu 890ddd
    #ifdef _DEBUG
Toshihiro Shimizu 890ddd
    if(intersections.size()==2 && intersections[0]==intersections[1])
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
      intersections.clear();
Toshihiro Shimizu 890ddd
      intersect( *oldStroke, pos, m_pointSize, intersections );   
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
    #endif
Toshihiro Shimizu 890ddd
    */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (intersections.empty()) {
Toshihiro Shimizu 890ddd
			//BASTEREBBE CONTROLLARE UN SOLO PUNTO PERCHE' SE LA
Toshihiro Shimizu 890ddd
			//STROKE NON INTERSECA IL CERCHIO E CONTENTIENE ALMENO
Toshihiro Shimizu 890ddd
			//UN PUNTO, LA CONTIENE TUTTA. MA SICCOME NON MI FIDO
Toshihiro Shimizu 890ddd
			//DELLA INTERSECT, NE CONTROLLO UN PAIO E AVVANTAGGIO (CON L' AND)
Toshihiro Shimizu 890ddd
			//IL NON CONTENIMENTO, DATO CHE E' MEGLIO CANCELLARE UNA COSA IN
Toshihiro Shimizu 890ddd
			// MENO, CHE UNA IN PIU'
Toshihiro Shimizu 890ddd
			if (tdistance2(oldStroke->getPoint(0), pos) < pointSize2 &&
Toshihiro Shimizu 890ddd
				tdistance2(oldStroke->getPoint(1), pos) < pointSize2) { //stroke tutta contenuta nella circonferenxa
Toshihiro Shimizu 890ddd
				if (*it != -1)
Toshihiro Shimizu 890ddd
					m_undo->addOldStroke(*it, vi->getVIStroke(i));
Toshihiro Shimizu 890ddd
				oneStrokeIndex[0] = i;
Toshihiro Shimizu 890ddd
				vi->removeStrokes(oneStrokeIndex, true, true);
Toshihiro Shimizu 890ddd
				it = m_indexes.erase(it);
Toshihiro Shimizu 890ddd
			} else { //non colpita
Toshihiro Shimizu 890ddd
				i++;
Toshihiro Shimizu 890ddd
				it++;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//------------------------ almeno un'intersezione ---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (intersections.size() == 1) {
Toshihiro Shimizu 890ddd
			if (oldStroke->isSelfLoop()) { // una sola intersezione di una stroke chiusa con un cerchio dovrebbe accadere
Toshihiro Shimizu 890ddd
				// solo in caso di sfioramento, quindi faccio finta di nulla
Toshihiro Shimizu 890ddd
				i++;
Toshihiro Shimizu 890ddd
				it++;
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (*it != -1)
Toshihiro Shimizu 890ddd
				m_undo->addOldStroke(*it, vi->getVIStroke(i));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			double w0 = intersections[0];
Toshihiro Shimizu 890ddd
			TThickPoint hitPoint = oldStroke->getThickPoint(w0);
Toshihiro Shimizu 890ddd
			int chunck;
Toshihiro Shimizu 890ddd
			double t;
Toshihiro Shimizu 890ddd
			oldStroke->getChunkAndT(w0, chunck, t);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			int chunckIndex;
Toshihiro Shimizu 890ddd
			double w1;
Toshihiro Shimizu 890ddd
			if (tdistance2(oldStroke->getPoint(0), pos) < pointSize2) {
Toshihiro Shimizu 890ddd
				chunckIndex = oldStroke->getChunkCount() - 1;
Toshihiro Shimizu 890ddd
				w1 = 1;
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				chunckIndex = 0;
Toshihiro Shimizu 890ddd
				w1 = 0;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			UINT cI;
Shinya Kitaoka 3bfa54
			std::vector<tthickpoint> points;</tthickpoint>
Toshihiro Shimizu 890ddd
			if (w1 == 0) {
Toshihiro Shimizu 890ddd
				for (cI = chunckIndex; cI < (UINT)chunck; cI++) {
Toshihiro Shimizu 890ddd
					points.push_back(oldStroke->getChunk(cI)->getThickP0());
Toshihiro Shimizu 890ddd
					points.push_back(oldStroke->getChunk(cI)->getThickP1());
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				TThickQuadratic t1, t2;
Toshihiro Shimizu 890ddd
				oldStroke->getChunk(chunck)->split(t, t1, t2);
Toshihiro Shimizu 890ddd
				points.push_back(t1.getThickP0());
Toshihiro Shimizu 890ddd
				points.push_back(t1.getThickP1());
Toshihiro Shimizu 890ddd
				points.push_back(hitPoint);
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				TThickQuadratic t1, t2;
Toshihiro Shimizu 890ddd
				oldStroke->getChunk(chunck)->split(t, t1, t2);
Toshihiro Shimizu 890ddd
				points.push_back(hitPoint);
Toshihiro Shimizu 890ddd
				points.push_back(t2.getThickP1());
Toshihiro Shimizu 890ddd
				points.push_back(t2.getThickP2());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				for (cI = chunck + 1; cI <= (UINT)chunckIndex; cI++) {
Toshihiro Shimizu 890ddd
					points.push_back(oldStroke->getChunk(cI)->getThickP1());
Toshihiro Shimizu 890ddd
					points.push_back(oldStroke->getChunk(cI)->getThickP2());
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			oldStroke->reshape(&(points[0]), points.size());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			vi->notifyChangedStrokes(i); //per adesso cosi', pero' e' lento
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			*it = -1;
Toshihiro Shimizu 890ddd
			i++;
Toshihiro Shimizu 890ddd
			it++;
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//---------- piu' intersezioni--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (intersections.size() & 1 && oldStroke->isSelfLoop()) { //non dovrebbe mai accadere
Toshihiro Shimizu 890ddd
			assert(0);
Toshihiro Shimizu 890ddd
			i++;
Toshihiro Shimizu 890ddd
			it++;
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (intersections.size() == 2 && intersections[0] == intersections[1]) { //solo sfiorata
Toshihiro Shimizu 890ddd
			i++;
Toshihiro Shimizu 890ddd
			it++;
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		UINT oldStrokeSize = vi->getStrokeCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (*it != -1)
Toshihiro Shimizu 890ddd
			m_undo->addOldStroke(*it, vi->getVIStroke(i));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		sortedWRanges.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (tdistance2(vi->getStroke(i)->getPoint(0), pos) > pointSize2) {
Toshihiro Shimizu 890ddd
			if (intersections[0] == 0.0)
Toshihiro Shimizu 890ddd
				intersections.erase(intersections.begin());
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				intersections.insert(intersections.begin(), 0.0);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (intersections[0] != 1.0)
Toshihiro Shimizu 890ddd
			intersections.push_back(1.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		sortedWRanges.reserve(intersections.size() / 2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (UINT j = 0; j < intersections.size() - 1; j += 2)
Shinya Kitaoka 2148c8
			sortedWRanges.push_back(std::make_pair(intersections[j], intersections[j + 1]));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (UINT kkk = 0; kkk < sortedWRanges.size() - 1; kkk++) {
Toshihiro Shimizu 890ddd
			assert(sortedWRanges[kkk].first < sortedWRanges[kkk].second);
Toshihiro Shimizu 890ddd
			assert(sortedWRanges[kkk].second <= sortedWRanges[kkk + 1].first);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		assert(sortedWRanges.back().first < sortedWRanges.back().second);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		vi->splitStroke(i, sortedWRanges);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		UINT addedStroke = vi->getStrokeCount() - (oldStrokeSize - 1); //-1 perche' e' quella tolta
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		i += addedStroke;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		*it = -1;
Toshihiro Shimizu 890ddd
		m_indexes.insert(it, addedStroke - 1, -1);
Toshihiro Shimizu 890ddd
		it = m_indexes.begin() + 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 EraserTool::erase(TVectorImageP vi, TRectD &rect)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (rect.x0 > rect.x1)
Toshihiro Shimizu 890ddd
		tswap(rect.x1, rect.x0);
Toshihiro Shimizu 890ddd
	if (rect.y0 > rect.y1)
Toshihiro Shimizu 890ddd
		tswap(rect.y1, rect.y0);
Toshihiro Shimizu 890ddd
	int i = 0;
Toshihiro Shimizu 890ddd
	int index = TTool::getApplication()->getCurrentLevelStyleIndex();
Shinya Kitaoka 3bfa54
	std::vector<int> eraseStrokes;</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXshSimpleLevel *level = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
	m_undo = new UndoEraser(level, getCurrentFid());
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)vi->getStrokeCount(); i++) {
Toshihiro Shimizu 890ddd
		if (!vi->inCurrentGroup(i))
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		TStroke *stroke = vi->getStroke(i);
Toshihiro Shimizu 890ddd
		if (!m_invertOption.getValue()) {
Toshihiro Shimizu 890ddd
			if ((!m_selective.getValue() || stroke->getStyle() == index) && rect.contains(stroke->getBBox())) {
Toshihiro Shimizu 890ddd
				m_undo->addOldStroke(i, vi->getVIStroke(i));
Toshihiro Shimizu 890ddd
				eraseStrokes.push_back(i);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			if ((!m_selective.getValue() || stroke->getStyle() == index) && !rect.contains(stroke->getBBox())) {
Toshihiro Shimizu 890ddd
				m_undo->addOldStroke(i, vi->getVIStroke(i));
Toshihiro Shimizu 890ddd
				eraseStrokes.push_back(i);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	for (i = (int)eraseStrokes.size() - 1; i >= 0; i--)
Toshihiro Shimizu 890ddd
		vi->deleteStroke(eraseStrokes[i]);
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->add(m_undo);
Toshihiro Shimizu 890ddd
	m_undo = 0;
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::stopErase(TVectorImageP vi)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(m_undo != 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT size = m_indexes.size();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(size == vi->getStrokeCount());
Toshihiro Shimizu 890ddd
	UINT i = 0;
Toshihiro Shimizu 890ddd
	for (; i < size; i++) {
Toshihiro Shimizu 890ddd
		if (m_indexes[i] == -1)
Toshihiro Shimizu 890ddd
			m_undo->addNewStroke(i, vi->getVIStroke(i));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->add(m_undo);
Toshihiro Shimizu 890ddd
	m_undo = 0;
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
	notifyImageChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_brushPos = m_mousePos = pos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_active = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TImageP image(getImage(true));
Toshihiro Shimizu 890ddd
	if (m_eraseType.getValue() == NORMAL_ERASE) {
Toshihiro Shimizu 890ddd
		if (TVectorImageP vi = image)
Toshihiro Shimizu 890ddd
			startErase(vi, pos /*,imageLocation*/);
Toshihiro Shimizu 890ddd
	} else if (m_eraseType.getValue() == RECT_ERASE) {
Toshihiro Shimizu 890ddd
		m_selectingRect.x0 = pos.x;
Toshihiro Shimizu 890ddd
		m_selectingRect.y0 = pos.y;
Toshihiro Shimizu 890ddd
		m_selectingRect.x1 = pos.x + 1;
Toshihiro Shimizu 890ddd
		m_selectingRect.y1 = pos.y + 1;
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
	} else if (m_eraseType.getValue() == FREEHAND_ERASE) {
Toshihiro Shimizu 890ddd
		startFreehand(pos);
Toshihiro Shimizu 890ddd
	} else if (m_eraseType.getValue() == POLYLINE_ERASE) {
Toshihiro Shimizu 890ddd
		addPointPolyline(pos);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_brushPos = m_mousePos = pos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_active)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TImageP image(getImage(true));
Toshihiro Shimizu 890ddd
	if (m_eraseType.getValue() == RECT_ERASE) {
Toshihiro Shimizu 890ddd
		m_selectingRect.x1 = pos.x;
Toshihiro Shimizu 890ddd
		m_selectingRect.y1 = pos.y;
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	} else if (m_eraseType.getValue() == NORMAL_ERASE) {
Toshihiro Shimizu 890ddd
		if (TVectorImageP vi = image)
Toshihiro Shimizu 890ddd
			erase(vi, pos);
Toshihiro Shimizu 890ddd
	} else if (m_eraseType.getValue() == FREEHAND_ERASE) {
Toshihiro Shimizu 890ddd
		freehandDrag(pos);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::multiEraseRect(TFrameId firstFrameId, TFrameId lastFrameId,
Toshihiro Shimizu 890ddd
								TRectD firstRect, TRectD lastRect, bool invert)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int r0 = firstFrameId.getNumber();
Toshihiro Shimizu 890ddd
	int r1 = lastFrameId.getNumber();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (r0 > r1) {
Toshihiro Shimizu 890ddd
		tswap(r0, r1);
Toshihiro Shimizu 890ddd
		tswap(firstFrameId, lastFrameId);
Toshihiro Shimizu 890ddd
		tswap(firstRect, lastRect);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if ((r1 - r0) < 1)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::vector<tframeid> allFids;</tframeid>
Toshihiro Shimizu 890ddd
	m_level->getFids(allFids);
Toshihiro Shimizu 890ddd
	std::vector<tframeid>::iterator i0 = allFids.begin();</tframeid>
Toshihiro Shimizu 890ddd
	while (i0 != allFids.end() && *i0 < firstFrameId)
Toshihiro Shimizu 890ddd
		i0++;
Toshihiro Shimizu 890ddd
	if (i0 == allFids.end())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	std::vector<tframeid>::iterator i1 = i0;</tframeid>
Toshihiro Shimizu 890ddd
	while (i1 != allFids.end() && *i1 <= lastFrameId)
Toshihiro Shimizu 890ddd
		i1++;
Toshihiro Shimizu 890ddd
	assert(i0 < i1);
Shinya Kitaoka 3bfa54
	std::vector<tframeid> fids(i0, i1);</tframeid>
Toshihiro Shimizu 890ddd
	int m = fids.size();
Toshihiro Shimizu 890ddd
	assert(m > 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->beginBlock();
Toshihiro Shimizu 890ddd
	for (int i = 0; i < m; ++i) {
Toshihiro Shimizu 890ddd
		TFrameId fid = fids[i];
Toshihiro Shimizu 890ddd
		assert(firstFrameId <= fid && fid <= lastFrameId);
Toshihiro Shimizu 890ddd
		TVectorImageP img = (TVectorImageP)m_level->getFrame(fid, true);
Toshihiro Shimizu 890ddd
		assert(img);
Toshihiro Shimizu 890ddd
		double t = m > 1 ? (double)i / (double)(m - 1) : 0.5;
Toshihiro Shimizu 890ddd
		TRectD rect = interpolateRect(firstRect, lastRect, t);
Toshihiro Shimizu 890ddd
		//m_level->setFrame(fid, img); //necessario: se la getFrame ha scompattato una img compressa, senza setFrame le modifiche sulla img fatte qui andrebbero perse.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Setto fid come corrente per notificare il cambiamento dell'immagine
Toshihiro Shimizu 890ddd
		TTool::Application *app = TTool::getApplication();
Toshihiro Shimizu 890ddd
		if (app) {
Toshihiro Shimizu 890ddd
			if (app->getCurrentFrame()->isEditingScene())
Toshihiro Shimizu 890ddd
				app->getCurrentFrame()->setFrame(fid.getNumber() - 1);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				app->getCurrentFrame()->setFid(fid);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		erase(img, rect);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		notifyImageChanged();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->endBlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::onImageChanged()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_multi.getValue())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	TTool::Application *application = TTool::getApplication();
Toshihiro Shimizu 890ddd
	if (!application)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	TXshSimpleLevel *xshl = 0;
Toshihiro Shimizu 890ddd
	if (application->getCurrentLevel()->getLevel())
Toshihiro Shimizu 890ddd
		xshl = application->getCurrentLevel()->getLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!xshl || m_level.getPointer() != xshl || (m_eraseType.getValue() == RECT_ERASE && m_selectingRect.isEmpty()) ||
Toshihiro Shimizu 890ddd
		((m_eraseType.getValue() == FREEHAND_ERASE || m_eraseType.getValue() == POLYLINE_ERASE) && !m_firstStroke))
Toshihiro Shimizu 890ddd
		resetMulti();
Toshihiro Shimizu 890ddd
	else if (m_firstFrameId == getCurrentFid())
Toshihiro Shimizu 890ddd
		m_firstFrameSelected = false; //nel caso sono passato allo stato 1 e torno all'immagine iniziale, torno allo stato iniziale
Toshihiro Shimizu 890ddd
	else {							  //cambio stato.
Toshihiro Shimizu 890ddd
		m_firstFrameSelected = true;
Toshihiro Shimizu 890ddd
		if (m_eraseType.getValue() == RECT_ERASE) {
Toshihiro Shimizu 890ddd
			assert(!m_selectingRect.isEmpty());
Toshihiro Shimizu 890ddd
			m_firstRect = m_selectingRect;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_active)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	TImageP image(getImage(true));
Toshihiro Shimizu 890ddd
	TVectorImageP vi = image;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTool::Application *application = TTool::getApplication();
Toshihiro Shimizu 890ddd
	if (!vi || !application)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	if (m_eraseType.getValue() == NORMAL_ERASE)
Toshihiro Shimizu 890ddd
		stopErase(vi);
Toshihiro Shimizu 890ddd
	else if (m_eraseType.getValue() == RECT_ERASE) {
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
Toshihiro Shimizu 890ddd
		if (m_multi.getValue()) {
Toshihiro Shimizu 890ddd
			if (m_firstFrameSelected) {
Toshihiro Shimizu 890ddd
				multiEraseRect(m_firstFrameId, getCurrentFid(), m_firstRect, m_selectingRect, m_invertOption.getValue());
Toshihiro Shimizu 890ddd
				invalidate(); //invalidate(m_selectingRect.enlarge(2));
Toshihiro Shimizu 890ddd
				if (e.isShiftPressed()) {
Toshihiro Shimizu 890ddd
					m_firstRect = m_selectingRect;
Toshihiro Shimizu 890ddd
					m_firstFrameId = getCurrentFid();
Toshihiro Shimizu 890ddd
				} else {
Toshihiro Shimizu 890ddd
					if (application->getCurrentFrame()->isEditingScene()) {
Toshihiro Shimizu 890ddd
						application->getCurrentColumn()->setColumnIndex(m_currCell.first);
Toshihiro Shimizu 890ddd
						application->getCurrentFrame()->setFrame(m_currCell.second);
Toshihiro Shimizu 890ddd
					} else
Toshihiro Shimizu 890ddd
						application->getCurrentFrame()->setFid(m_veryFirstFrameId);
Toshihiro Shimizu 890ddd
					resetMulti();
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				if (application->getCurrentFrame()->isEditingScene())
Toshihiro Shimizu 890ddd
					m_currCell = std::pair<int, int="">(application->getCurrentColumn()->getColumnIndex(),</int,>
Toshihiro Shimizu 890ddd
													 application->getCurrentFrame()->getFrame());
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			erase(vi, m_selectingRect);
Toshihiro Shimizu 890ddd
			invalidate();
Toshihiro Shimizu 890ddd
			notifyImageChanged();
Toshihiro Shimizu 890ddd
			m_selectingRect.empty();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else if (m_eraseType.getValue() == FREEHAND_ERASE) {
Toshihiro Shimizu 890ddd
		closeFreehand(pos);
Toshihiro Shimizu 890ddd
		if (m_multi.getValue()) {
Toshihiro Shimizu 890ddd
			multiEreserRegion(m_stroke, e);
Toshihiro Shimizu 890ddd
			invalidate();
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			eraseRegion(vi, m_stroke);
Toshihiro Shimizu 890ddd
			invalidate();
Toshihiro Shimizu 890ddd
			notifyImageChanged();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	m_active = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!Viene chiusa la polyline e si da il via alla cancellazione.
Toshihiro Shimizu 890ddd
/*!Viene creato lo \b stroke rappresentante la polyline disegnata. 
Toshihiro Shimizu 890ddd
  Se e' selzionato il metodo di cancellazione "frame range" viene richiamato il metodo \b multiEreserRegion, altrimenti
Toshihiro Shimizu 890ddd
  viene richiamato il metodo \b eraseRegion*/
Toshihiro Shimizu 890ddd
void EraserTool::leftButtonDoubleClick(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi = getImage(true);
Toshihiro Shimizu 890ddd
	if (m_eraseType.getValue() == POLYLINE_ERASE) {
Toshihiro Shimizu 890ddd
		closePolyline(pos);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
		std::vector<tthickpoint> strokePoints;</tthickpoint>
Toshihiro Shimizu 890ddd
		for (UINT i = 0; i < m_polyline.size() - 1; i++) {
Toshihiro Shimizu 890ddd
			strokePoints.push_back(TThickPoint(m_polyline[i], 1));
Toshihiro Shimizu 890ddd
			strokePoints.push_back(TThickPoint(0.5 * (m_polyline[i] + m_polyline[i + 1]), 1));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		strokePoints.push_back(TThickPoint(m_polyline.back(), 1));
Toshihiro Shimizu 890ddd
		m_polyline.clear();
Toshihiro Shimizu 890ddd
		TStroke *stroke = new TStroke(strokePoints);
Toshihiro Shimizu 890ddd
		assert(stroke->getPoint(0) == stroke->getPoint(1));
Toshihiro Shimizu 890ddd
		if (m_multi.getValue())
Toshihiro Shimizu 890ddd
			multiEreserRegion(stroke, e);
Toshihiro Shimizu 890ddd
		else {
Toshihiro Shimizu 890ddd
			eraseRegion(vi, stroke);
Toshihiro Shimizu 890ddd
			notifyImageChanged();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::mouseMove(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct Locals {
Toshihiro Shimizu 890ddd
		EraserTool *m_this;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		void setValue(TDoubleProperty &prop, double value)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			prop.setValue(value);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			m_this->onPropertyChanged(prop.getName());
Toshihiro Shimizu 890ddd
			TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		void addValue(TDoubleProperty &prop, double add)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			const TDoubleProperty::Range &range = prop.getRange();
Toshihiro Shimizu 890ddd
			setValue(prop, tcrop(prop.getValue() + add, range.first, range.second));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	} locals = {this};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	switch (e.getModifiersMask()) {
Toshihiro Shimizu 890ddd
	case TMouseEvent::ALT_KEY: {
Toshihiro Shimizu 890ddd
		// User wants to alter the maximum brush size
Toshihiro Shimizu 890ddd
		const TPointD &diff = pos - m_mousePos;
Toshihiro Shimizu 890ddd
		double add = (fabs(diff.x) > fabs(diff.y)) ? diff.x : diff.y;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		locals.addValue(m_toolSize, add);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DEFAULT:
Toshihiro Shimizu 890ddd
		m_brushPos = pos;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_oldMousePos = m_mousePos = pos;
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
bool EraserTool::onPropertyChanged(std::string propertyName)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	EraseVectorType = toString(m_eraseType.getValue());
Toshihiro Shimizu 890ddd
	EraseVectorSize = m_toolSize.getValue();
Toshihiro Shimizu 890ddd
	EraseVectorSelective = m_selective.getValue();
Toshihiro Shimizu 890ddd
	EraseVectorInvert = m_invertOption.getValue();
Toshihiro Shimizu 890ddd
	EraseVectorRange = m_multi.getValue();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double x = m_toolSize.getValue();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double minRange = 1;
Toshihiro Shimizu 890ddd
	double maxRange = 100;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double minSize = 2;
Toshihiro Shimizu 890ddd
	double maxSize = 100;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_pointSize = ((x - minRange) / (maxRange - minRange) * (maxSize - minSize) + minSize) * 0.5;
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::onEnter()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_firstTime) {
Toshihiro Shimizu 890ddd
		m_toolSize.setValue(EraseVectorSize);
Toshihiro Shimizu 890ddd
		m_eraseType.setValue(toWideString((EraseVectorType.getValue())));
Toshihiro Shimizu 890ddd
		m_selective.setValue(EraseVectorSelective ? 1 : 0);
Toshihiro Shimizu 890ddd
		m_invertOption.setValue(EraseVectorInvert ? 1 : 0);
Toshihiro Shimizu 890ddd
		m_multi.setValue(EraseVectorRange ? 1 : 0);
Toshihiro Shimizu 890ddd
		m_firstTime = false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double x = m_toolSize.getValue();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double minRange = 1;
Toshihiro Shimizu 890ddd
	double maxRange = 100;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double minSize = 2;
Toshihiro Shimizu 890ddd
	double maxSize = 100;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_pointSize = ((x - minRange) / (maxRange - minRange) * (maxSize - minSize) + minSize) * 0.5;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//  getApplication()->editImage();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::onLeave()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	draw();
Toshihiro Shimizu 890ddd
	m_pointSize = -1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::onActivate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	resetMulti();
Toshihiro Shimizu 890ddd
	onEnter();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!Viene aggiunto \b pos a \b m_track e disegnato il primo pezzetto del lazzo. Viene inizializzato \b m_firstPos
Toshihiro Shimizu 890ddd
void EraserTool::startFreehand(const TPointD &pos)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_track.clear();
Toshihiro Shimizu 890ddd
	m_firstPos = pos;
Toshihiro Shimizu 890ddd
	m_track.add(TThickPoint(pos, m_thick), getPixelSize() * getPixelSize());
Toshihiro Shimizu 890ddd
	TPointD dpiScale = m_viewer->getDpiScale();
Toshihiro Shimizu 890ddd
#if defined(MACOSX)
Toshihiro Shimizu 890ddd
//			m_viewer->prepareForegroundDrawing();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	//	m_viewer->makeCurrent();
Toshihiro Shimizu 890ddd
	TPixel color = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg ? TPixel32::White : TPixel32::Black;
Toshihiro Shimizu 890ddd
	tglColor(color);
Toshihiro Shimizu 890ddd
	m_viewer->startForegroundDrawing();
Toshihiro Shimizu 890ddd
	glPushMatrix();
Toshihiro Shimizu 890ddd
	tglMultMatrix(getMatrix());
Toshihiro Shimizu 890ddd
	glScaled(dpiScale.x, dpiScale.y, 1);
Toshihiro Shimizu 890ddd
	m_track.drawLastFragments();
Toshihiro Shimizu 890ddd
	glPopMatrix();
Toshihiro Shimizu 890ddd
	m_viewer->endForegroundDrawing();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!Viene aggiunto \b pos a \b m_track e disegnato un altro pezzetto del lazzo.
Toshihiro Shimizu 890ddd
void EraserTool::freehandDrag(const TPointD &pos)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
#if defined(MACOSX)
Toshihiro Shimizu 890ddd
//		m_viewer->enableRedraw(false);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_viewer->startForegroundDrawing();
Toshihiro Shimizu 890ddd
	TPixel color = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg ? TPixel32::White : TPixel32::Black;
Toshihiro Shimizu 890ddd
	tglColor(color);
Toshihiro Shimizu 890ddd
	glPushMatrix();
Toshihiro Shimizu 890ddd
	tglMultMatrix(getMatrix());
Toshihiro Shimizu 890ddd
	TPointD dpiScale = m_viewer->getDpiScale();
Toshihiro Shimizu 890ddd
	glScaled(dpiScale.x, dpiScale.y, 1);
Toshihiro Shimizu 890ddd
	m_track.add(TThickPoint(pos, m_thick), getPixelSize() * getPixelSize());
Toshihiro Shimizu 890ddd
	m_track.drawLastFragments();
Toshihiro Shimizu 890ddd
	glPopMatrix();
Toshihiro Shimizu 890ddd
	m_viewer->endForegroundDrawing();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!Viene chiuso il lazzo (si aggiunge l'ultimo punto ad m_track) e viene creato lo stroke rappresentante il lazzo.
Toshihiro Shimizu 890ddd
void EraserTool::closeFreehand(const TPointD &pos)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
#if defined(MACOSX)
Toshihiro Shimizu 890ddd
//		m_viewer->enableRedraw(true);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	if (m_track.isEmpty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	m_track.add(TThickPoint(m_firstPos, m_thick), getPixelSize() * getPixelSize());
Toshihiro Shimizu 890ddd
	m_track.filterPoints();
Toshihiro Shimizu 890ddd
	double error = (30.0 / 11) * sqrt(getPixelSize() * getPixelSize());
Toshihiro Shimizu 890ddd
	m_stroke = m_track.makeStroke(error);
Toshihiro Shimizu 890ddd
	m_stroke->setStyle(1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!Viene aggiunto un punto al vettore m_polyline.
Toshihiro Shimizu 890ddd
void EraserTool::addPointPolyline(const TPointD &pos)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_firstPos = pos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD dpiScale = m_viewer->getDpiScale();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(MACOSX)
Toshihiro Shimizu 890ddd
//		 m_viewer->prepareForegroundDrawing();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	//      m_viewer->makeCurrent();
Toshihiro Shimizu 890ddd
	TPixel color = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg ? TPixel32::White : TPixel32::Black;
Toshihiro Shimizu 890ddd
	tglColor(color);
Toshihiro Shimizu 890ddd
//	  m_viewer->startForegroundDrawing();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(MACOSX)
Toshihiro Shimizu 890ddd
//		m_viewer->enableRedraw(m_eraseType.getValue() == POLYLINE_ERASE);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glPushMatrix();
Toshihiro Shimizu 890ddd
	glScaled(dpiScale.x, dpiScale.y, 1);
Toshihiro Shimizu 890ddd
	m_polyline.push_back(pos);
Toshihiro Shimizu 890ddd
	glPopMatrix();
Toshihiro Shimizu 890ddd
	//	  m_viewer->endForegroundDrawing();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!Agginge l'ultimo pos a \b m_polyline e chiude la spezzata (aggiunge \b m_polyline.front() alla fine del vettore)
Toshihiro Shimizu 890ddd
void EraserTool::closePolyline(const TPointD &pos)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_polyline.size() <= 1)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	if (m_polyline.back() != pos)
Toshihiro Shimizu 890ddd
		m_polyline.push_back(pos);
Toshihiro Shimizu 890ddd
	if (m_polyline.back() != m_polyline.front())
Toshihiro Shimizu 890ddd
		m_polyline.push_back(m_polyline.front());
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!Cancella stroke presenti in \b vi e contenuti nella regione delimitata da \b stroke.
Toshihiro Shimizu 890ddd
/*!Vengono cercati gli stroke da cancellare facendo i dovuti controlli sui parametri \b m_invertOption e \b m_selective.
Toshihiro Shimizu 890ddd
	Se uno stroke deve essere cancellato viene inserito in \b eraseStrokes.
Toshihiro Shimizu 890ddd
	Gli stroke vengono cancellati tutti alla fine.*/
Toshihiro Shimizu 890ddd
void EraserTool::eraseRegion(const TVectorImageP vi, TStroke *stroke) //, const TImageLocation &imageLocation)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!vi || !stroke)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	TVectorImage eraseImg;
Toshihiro Shimizu 890ddd
	TStroke *eraseStroke = new TStroke(*stroke);
Toshihiro Shimizu 890ddd
	eraseImg.addStroke(eraseStroke);
Toshihiro Shimizu 890ddd
	eraseImg.findRegions();
Toshihiro Shimizu 890ddd
	int strokeIndex, regionIndex, colorStyle;
Toshihiro Shimizu 890ddd
	colorStyle = TTool::getApplication()->getCurrentLevelStyleIndex();
Shinya Kitaoka 3bfa54
	std::vector<int> eraseStrokes;</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXshSimpleLevel *level = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
	m_undo = new UndoEraser(level, getCurrentFid());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_invertOption.getValue()) {
Toshihiro Shimizu 890ddd
		for (strokeIndex = 0; strokeIndex < (int)vi->getStrokeCount(); strokeIndex++) {
Toshihiro Shimizu 890ddd
			if (!vi->inCurrentGroup(strokeIndex))
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
			TStroke *currentStroke = vi->getStroke(strokeIndex);
Toshihiro Shimizu 890ddd
			for (regionIndex = 0; regionIndex < (int)eraseImg.getRegionCount(); regionIndex++) {
Toshihiro Shimizu 890ddd
				TRegion *region = eraseImg.getRegion(regionIndex);
Toshihiro Shimizu 890ddd
				if ((!m_selective.getValue() || (m_selective.getValue() && currentStroke->getStyle() == colorStyle)) &&
Toshihiro Shimizu 890ddd
					region->contains(*currentStroke, true)) {
Toshihiro Shimizu 890ddd
					eraseStrokes.push_back(strokeIndex);
Toshihiro Shimizu 890ddd
					m_undo->addOldStroke(strokeIndex, vi->getVIStroke(strokeIndex));
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		for (strokeIndex = 0; strokeIndex < (int)vi->getStrokeCount(); strokeIndex++) {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TStroke *currentStroke = vi->getStroke(strokeIndex);
Toshihiro Shimizu 890ddd
			bool eraseIt = false;
Toshihiro Shimizu 890ddd
			for (regionIndex = 0; regionIndex < (int)eraseImg.getRegionCount(); regionIndex++) {
Toshihiro Shimizu 890ddd
				TRegion *region = eraseImg.getRegion(regionIndex);
Toshihiro Shimizu 890ddd
				if (!m_selective.getValue() || (m_selective.getValue() && currentStroke->getStyle() == colorStyle))
Toshihiro Shimizu 890ddd
					eraseIt = true;
Toshihiro Shimizu 890ddd
				if (region->contains(*currentStroke, true)) {
Toshihiro Shimizu 890ddd
					eraseIt = false;
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			if (eraseIt) {
Toshihiro Shimizu 890ddd
				m_undo->addOldStroke(strokeIndex, vi->getVIStroke(strokeIndex));
Toshihiro Shimizu 890ddd
				eraseStrokes.push_back(strokeIndex);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = (int)eraseStrokes.size() - 1; i >= 0; i--)
Toshihiro Shimizu 890ddd
		vi->deleteStroke(eraseStrokes[i]);
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
//!Viene richiamata la doErase sui frame compresi tra \b firstFrameId e \b lastFrameId.
Toshihiro Shimizu 890ddd
/*!Viene caricato il vettore \b fids con i TFrameId delle immagini sulle quali si deve effettuare una cancellazione.*/
Toshihiro Shimizu 890ddd
void EraserTool::doMultiErase(TFrameId &firstFrameId, TFrameId &lastFrameId,
Toshihiro Shimizu 890ddd
							  const TStroke *firstStroke, const TStroke *lastStroke)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXshSimpleLevel *sl = TTool::getApplication()->getCurrentLevel()->getLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
	TStroke *first = new TStroke();
Toshihiro Shimizu 890ddd
	TStroke *last = new TStroke();
Toshihiro Shimizu 890ddd
	*first = *firstStroke;
Toshihiro Shimizu 890ddd
	*last = *lastStroke;
Toshihiro Shimizu 890ddd
	TVectorImageP firstImage = new TVectorImage();
Toshihiro Shimizu 890ddd
	TVectorImageP lastImage = new TVectorImage();
Toshihiro Shimizu 890ddd
	firstImage->addStroke(first);
Toshihiro Shimizu 890ddd
	lastImage->addStroke(last);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool backward = false;
Toshihiro Shimizu 890ddd
	if (firstFrameId > lastFrameId) {
Toshihiro Shimizu 890ddd
		tswap(firstFrameId, lastFrameId);
Toshihiro Shimizu 890ddd
		backward = true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	assert(firstFrameId <= lastFrameId);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::vector<tframeid> allFids;</tframeid>
Toshihiro Shimizu 890ddd
	sl->getFids(allFids);
Toshihiro Shimizu 890ddd
	std::vector<tframeid>::iterator i0 = allFids.begin();</tframeid>
Toshihiro Shimizu 890ddd
	while (i0 != allFids.end() && *i0 < firstFrameId)
Toshihiro Shimizu 890ddd
		i0++;
Toshihiro Shimizu 890ddd
	if (i0 == allFids.end())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	std::vector<tframeid>::iterator i1 = i0;</tframeid>
Toshihiro Shimizu 890ddd
	while (i1 != allFids.end() && *i1 <= lastFrameId)
Toshihiro Shimizu 890ddd
		i1++;
Toshihiro Shimizu 890ddd
	assert(i0 < i1);
Shinya Kitaoka 3bfa54
	std::vector<tframeid> fids(i0, i1);</tframeid>
Toshihiro Shimizu 890ddd
	int m = fids.size();
Toshihiro Shimizu 890ddd
	assert(m > 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->beginBlock();
Toshihiro Shimizu 890ddd
	for (int i = 0; i < m; ++i) {
Toshihiro Shimizu 890ddd
		TFrameId fid = fids[i];
Toshihiro Shimizu 890ddd
		assert(firstFrameId <= fid && fid <= lastFrameId);
Toshihiro Shimizu 890ddd
		double t = m > 1 ? (double)i / (double)(m - 1) : 0.5;
Toshihiro Shimizu 890ddd
		//Setto il fid come corrente per notificare il cambiamento dell'immagine
Toshihiro Shimizu 890ddd
		TTool::Application *app = TTool::getApplication();
Toshihiro Shimizu 890ddd
		if (app) {
Toshihiro Shimizu 890ddd
			if (app->getCurrentFrame()->isEditingScene())
Toshihiro Shimizu 890ddd
				app->getCurrentFrame()->setFrame(fid.getNumber() - 1);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				app->getCurrentFrame()->setFid(fid);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		doErase(backward ? 1 - t : t, sl, fid, firstImage, lastImage);
Toshihiro Shimizu 890ddd
		notifyImageChanged();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->endBlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!Viene richiamata la \b eraseRegion per il frame giusto nel caso della modalita' "Frame Range".
Toshihiro Shimizu 890ddd
/*!Nei casi in cui \b t e' diverso da zero e uno, viene generata una nuova \b TVectorImageP richiamando la \b TInbetween. 
Toshihiro Shimizu 890ddd
	La nuova immagine contiene lo stroke da dare alla eraseRegion. \b fid e' il TFrameId dell'immagine sulla quale 
Toshihiro Shimizu 890ddd
	bisogna effettuare la cancellazione.*/
Toshihiro Shimizu 890ddd
void EraserTool::doErase(double t, const TXshSimpleLevelP &sl, const TFrameId &fid,
Toshihiro Shimizu 890ddd
						 const TVectorImageP &firstImage, const TVectorImageP &lastImage)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//	TImageLocation imageLocation(m_level->getName(),fid);
Toshihiro Shimizu 890ddd
	TVectorImageP img = sl->getFrame(fid, true);
Toshihiro Shimizu 890ddd
	if (t == 0)
Toshihiro Shimizu 890ddd
		eraseRegion(img, firstImage->getStroke(0)); //,imageLocation);
Toshihiro Shimizu 890ddd
	else if (t == 1)
Toshihiro Shimizu 890ddd
		eraseRegion(img, lastImage->getStroke(0)); //,imageLocation);
Toshihiro Shimizu 890ddd
	else {
Toshihiro Shimizu 890ddd
		assert(firstImage->getStrokeCount() == 1);
Toshihiro Shimizu 890ddd
		assert(lastImage->getStrokeCount() == 1);
Toshihiro Shimizu 890ddd
		TVectorImageP vi = TInbetween(firstImage, lastImage).tween(t);
Toshihiro Shimizu 890ddd
		assert(vi->getStrokeCount() == 1);
Toshihiro Shimizu 890ddd
		eraseRegion(img, vi->getStroke(0)); //,imageLocation);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!Effettua la cancellazione nella modalita' "Frame range".
Toshihiro Shimizu 890ddd
/*! Se il primo frame e' gia stato selezionato richiama la \b doMultiErase; altrimenti viene inizializzato 
Toshihiro Shimizu 890ddd
 \b m_firstStroke.*/
Toshihiro Shimizu 890ddd
void EraserTool::multiEreserRegion(TStroke *stroke, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTool::Application *application = TTool::getApplication();
Toshihiro Shimizu 890ddd
	if (!application)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_firstFrameSelected) {
Toshihiro Shimizu 890ddd
		if (m_firstStroke && stroke) {
Toshihiro Shimizu 890ddd
			TFrameId tmpFrameId = getCurrentFid();
Toshihiro Shimizu 890ddd
			doMultiErase(m_firstFrameId, tmpFrameId, m_firstStroke, stroke);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (e.isShiftPressed()) {
Toshihiro Shimizu 890ddd
			m_firstStroke = new TStroke(*stroke);
Toshihiro Shimizu 890ddd
			m_firstFrameId = getCurrentFid();
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			if (application->getCurrentFrame()->isEditingScene()) {
Toshihiro Shimizu 890ddd
				application->getCurrentColumn()->setColumnIndex(m_currCell.first);
Toshihiro Shimizu 890ddd
				application->getCurrentFrame()->setFrame(m_currCell.second);
Toshihiro Shimizu 890ddd
			} else
Toshihiro Shimizu 890ddd
				application->getCurrentFrame()->setFid(m_veryFirstFrameId);
Toshihiro Shimizu 890ddd
			resetMulti();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		m_firstStroke = new TStroke(*stroke);
Toshihiro Shimizu 890ddd
		if (application->getCurrentFrame()->isEditingScene())
Toshihiro Shimizu 890ddd
			m_currCell = std::pair<int, int="">(application->getCurrentColumn()->getColumnIndex(),</int,>
Toshihiro Shimizu 890ddd
											 application->getCurrentFrame()->getFrame());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! ドラッグ中にツールが切り替わった場合、Erase終了処理を行う
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
void EraserTool::onDeactivate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_active)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_active = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//TODO : finishing erase procedure is only available for normal type. Supporting other types is needed. 2016/1/22 shun_iwasawa
Toshihiro Shimizu 890ddd
	if (m_eraseType.getValue() != NORMAL_ERASE)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TImageP image(getImage(true));
Toshihiro Shimizu 890ddd
	TVectorImageP vi = image;
Toshihiro Shimizu 890ddd
	TTool::Application *application = TTool::getApplication();
Toshihiro Shimizu 890ddd
	if (!vi || !application)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	stopErase(vi);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TTool *getEraserTool() {return &eraserTool;}