Blob Blame Raw
#pragma once

#ifndef RASTERSELECTIONTOOL_INCLUDED
#define RASTERSELECTIONTOOL_INCLUDED

#include "selectiontool.h"
#include "setsaveboxtool.h"
#include "tools/rasterselection.h"

// forward declaration
class RasterSelectionTool;
class VectorFreeDeformer;

//=============================================================================
// RasterFreeDeformer
//-----------------------------------------------------------------------------

class RasterFreeDeformer : public FreeDeformer
{
	TRasterP m_ras;
	TRasterP m_newRas;
	bool m_noAntialiasing;

public:
	RasterFreeDeformer(TRasterP ras);
	~RasterFreeDeformer();

	/*! Set \b index point to \b p, with index from 0 to 3. */
	void setPoint(int index, const TPointD &p);
	/*! Helper function. */
	void setPoints(const TPointD &p0, const TPointD &p1, const TPointD &p2, const TPointD &p3);
	TRasterP getImage() const { return m_newRas; }
	void deformImage();
	void setNoAntialiasing(bool value) { m_noAntialiasing = value; }
};

//=============================================================================
// DragSelectionTool
//-----------------------------------------------------------------------------

namespace DragSelectionTool
{

//=============================================================================
// UndoRasterDeform
//-----------------------------------------------------------------------------

class UndoRasterDeform : public TUndo
{
	static int m_id;
	RasterSelectionTool *m_tool;
	std::string m_oldFloatingImageId, m_newFloatingImageId;
	std::vector<TStroke> m_newStrokes;
	std::vector<TStroke> m_oldStrokes;
	DragSelectionTool::DeformValues m_oldDeformValues, m_newDeformValues;
	FourPoints m_oldBBox, m_newBBox;
	TPointD m_oldCenter, m_newCenter;

	TDimension m_dim;
	int m_pixelSize;

public:
	UndoRasterDeform(RasterSelectionTool *tool);
	~UndoRasterDeform();

	void registerRasterDeformation();

	void undo() const;
	void redo() const;

	int getSize() const;

	QString getHistoryString()
	{
		return QObject::tr("Deform Raster");
	}
};

//=============================================================================
// UndoRasterTransform
//-----------------------------------------------------------------------------

class UndoRasterTransform : public TUndo
{
	RasterSelectionTool *m_tool;
	TAffine m_oldTransform, m_newTransform;
	TPointD m_oldCenter, m_newCenter;
	FourPoints m_oldBbox, m_newBbox;
	DragSelectionTool::DeformValues m_oldDeformValues, m_newDeformValues;

public:
	UndoRasterTransform(RasterSelectionTool *tool);
	void setChangedValues();
	void undo() const;
	void redo() const;

	int getSize() const { return sizeof(*this); }

	QString getHistoryString()
	{
		return QObject::tr("Transform Raster");
	}
};

//=============================================================================
// RasterDeformTool
//-----------------------------------------------------------------------------

class RasterDeformTool : public DeformTool
{
protected:
	TAffine m_transform;
	UndoRasterTransform *m_transformUndo;
	UndoRasterDeform *m_deformUndo;

	//!It's true when use RasterFreeDeformer
	bool m_isFreeDeformer;

	void applyTransform(FourPoints bbox);
	void applyTransform(TAffine aff, bool modifyCenter);
	void addTransformUndo();

	void leftButtonDrag(const TPointD &pos, const TMouseEvent &e){};
	void draw(){};

public:
	RasterDeformTool(RasterSelectionTool *tool, bool freeDeformer);
};

//=============================================================================
// RasterRotationTool
//-----------------------------------------------------------------------------

class RasterRotationTool : public RasterDeformTool
{
	Rotation *m_rotation;

public:
	RasterRotationTool(RasterSelectionTool *tool);
	void transform(TAffine aff, double angle);
	void leftButtonDrag(const TPointD &pos, const TMouseEvent &e);
	void draw();
};

//=============================================================================
// RasterFreeDeformTool
//-----------------------------------------------------------------------------

class RasterFreeDeformTool : public RasterDeformTool
{
	FreeDeform *m_freeDeform;

public:
	RasterFreeDeformTool(RasterSelectionTool *tool);
	void leftButtonDrag(const TPointD &pos, const TMouseEvent &e);
};

//=============================================================================
// RasterMoveSelectionTool
//-----------------------------------------------------------------------------

class RasterMoveSelectionTool : public RasterDeformTool
{
	MoveSelection *m_moveSelection;

public:
	RasterMoveSelectionTool(RasterSelectionTool *tool);
	void transform(TAffine aff);
	void leftButtonDown(const TPointD &pos, const TMouseEvent &e);
	void leftButtonDrag(const TPointD &pos, const TMouseEvent &e);
};

//=============================================================================
// RasterScaleTool
//-----------------------------------------------------------------------------

class RasterScaleTool : public RasterDeformTool
{
	Scale *m_scale;

public:
	RasterScaleTool(RasterSelectionTool *tool, int type);
	/*! Return scale value. */
	TPointD transform(int index, TPointD newPos);
	void leftButtonDown(const TPointD &pos, const TMouseEvent &e);
	void leftButtonDrag(const TPointD &pos, const TMouseEvent &e);
};

} //namespace DragSelectionTool

//=============================================================================
// RasterSelectionTool
//-----------------------------------------------------------------------------

class RasterSelectionTool : public SelectionTool
{
	Q_DECLARE_TR_FUNCTIONS(RasterSelectionTool)

	RasterSelection m_rasterSelection;
	int m_transformationCount;

	//!Used in ToonzRasterImage to switch from selection tool to modify savebox tool.
	TBoolProperty m_modifySavebox;
	SetSaveboxTool *m_setSaveboxTool;
	TBoolProperty m_noAntialiasing;

	//!Used to deform bbox strokes.
	VectorFreeDeformer *m_selectionFreeDeformer;

	void modifySelectionOnClick(TImageP image, const TPointD &pos, const TMouseEvent &e);

	void drawFloatingSelection();

public:
	RasterSelectionTool(int targetType);

	void setBBox(const DragSelectionTool::FourPoints &points, int index = 0);

	void setNewFreeDeformer();
	VectorFreeDeformer *getSelectionFreeDeformer() const;

	bool isFloating() const;

	void leftButtonDown(const TPointD &pos, const TMouseEvent &);
	void mouseMove(const TPointD &pos, const TMouseEvent &e);
	void leftButtonDrag(const TPointD &pos, const TMouseEvent &);
	void leftButtonUp(const TPointD &pos, const TMouseEvent &);
	void leftButtonDoubleClick(const TPointD &, const TMouseEvent &e);

	void draw();

	TSelection *getSelection();
	bool isSelectionEmpty();

	void computeBBox();

	void doOnActivate();
	void doOnDeactivate();

	void onImageChanged();

	void transformFloatingSelection(const TAffine &affine, const TPointD &center,
									const DragSelectionTool::FourPoints &points);
	void increaseTransformationCount();
	void decreaseTransformationCount();

	void onActivate();
	TBoolProperty *getModifySaveboxProperty()
	{
		if (m_targetType & ToonzImage)
			return &m_modifySavebox;
		return 0;
	}
	bool onPropertyChanged(std::string propertyName);
	bool getNoAntialiasingValue() { return m_noAntialiasing.getValue(); }

protected:
	void updateTranslation();
};

#endif //RASTERSELECTIONTOOL_INCLUDED