|
Toshihiro Shimizu |
890ddd |
|
|
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 |
|
|
Toshihiro Shimizu |
890ddd |
#include "tstrokeutil.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tmathutil.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tgl.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstroke.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tobjecthandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/txshlevelhandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tstageobject.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef _DEBUG
|
|
Toshihiro Shimizu |
890ddd |
#include "tcolorstyles.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tsimplecolorstyles.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstrokeoutline.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tpalette.h"
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
using namespace ToolUtils;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const int MY_ERROR = -1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
// Iron
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// index must be between 0 and controlPointCount-1
|
|
Toshihiro Shimizu |
890ddd |
inline bool isIncluded(int index, int left, int rigth)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (left < rigth) {
|
|
Toshihiro Shimizu |
890ddd |
return left <= index && index <= rigth;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
return left <= index || index <= rigth;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
// IronTool
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class IronTool : public TTool
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TStroke *m_strokeRef, *m_oldStroke;
|
|
Toshihiro Shimizu |
890ddd |
TUndo *m_undo;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DoublePair m_range;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool m_draw;
|
|
Toshihiro Shimizu |
890ddd |
bool m_dragged;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint m_cursor;
|
|
Toshihiro Shimizu |
890ddd |
int m_selectedStroke;
|
|
Toshihiro Shimizu |
890ddd |
TPointD m_beginPoint;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int m_cpIndexMin, m_cpIndexMax;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool m_active;
|
|
Toshihiro Shimizu |
890ddd |
int m_cursorId;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
IronTool()
|
|
Toshihiro Shimizu |
890ddd |
: TTool("T_Iron"), m_strokeRef(0), m_draw(false), m_active(false), m_dragged(false), m_undo(0), m_cpIndexMin(-1), m_cpIndexMax(-1), m_oldStroke(0), m_cursorId(ToolCursor::IronCursor)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
bind(TTool::Vectors);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
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 |
if (m_draw && (TVectorImageP)getImage(false)) {
|
|
Toshihiro Shimizu |
890ddd |
glColor3d(1, 0, 1);
|
|
Toshihiro Shimizu |
890ddd |
if (m_cursor.thick > 0)
|
|
Toshihiro Shimizu |
890ddd |
tglDrawCircle(m_cursor, m_cursor.thick);
|
|
Toshihiro Shimizu |
890ddd |
tglDrawCircle(m_cursor, m_cursor.thick + 4 * getPixelSize());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void leftButtonDown(const TPointD &pos, const TMouseEvent &)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_active)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
assert(m_undo == 0);
|
|
Toshihiro Shimizu |
890ddd |
m_active = false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TVectorImageP vi = TImageP(getImage(true));
|
|
Toshihiro Shimizu |
890ddd |
if (!vi)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// select nearest stroke and finds its parameter
|
|
Toshihiro Shimizu |
890ddd |
double dist;
|
|
Toshihiro Shimizu |
890ddd |
UINT stroke;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!vi->getNearestStroke(pos, m_range.first, stroke, dist)) {
|
|
Toshihiro Shimizu |
890ddd |
m_strokeRef = 0;
|
|
Toshihiro Shimizu |
890ddd |
m_selectedStroke = MY_ERROR;
|
|
Toshihiro Shimizu |
890ddd |
m_draw = false;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
m_draw = true;
|
|
Toshihiro Shimizu |
890ddd |
m_active = true;
|
|
Toshihiro Shimizu |
890ddd |
m_strokeRef = vi->getStroke(stroke);
|
|
Toshihiro Shimizu |
890ddd |
m_selectedStroke = stroke;
|
|
Toshihiro Shimizu |
890ddd |
m_beginPoint = m_strokeRef->getPoint(m_range.first);
|
|
Toshihiro Shimizu |
890ddd |
m_oldStroke = new TStroke(*vi->getStroke(stroke));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_range.second = m_range.first;
|
|
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 |
else {
|
|
Toshihiro Shimizu |
890ddd |
TXshSimpleLevel *sl = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
|
|
Toshihiro Shimizu |
890ddd |
assert(sl);
|
|
Toshihiro Shimizu |
890ddd |
TFrameId id = getCurrentFid();
|
|
Toshihiro Shimizu |
890ddd |
m_undo = new UndoModifyStrokeAndPaint(sl, id, stroke);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_strokeRef)
|
|
Toshihiro Shimizu |
890ddd |
m_cpIndexMin = m_strokeRef->getControlPointCount();
|
|
Toshihiro Shimizu |
890ddd |
m_cpIndexMax = -1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void leftButtonDrag(const TPointD &pos, const TMouseEvent &e)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TVectorImageP vi(getImage(true));
|
|
Toshihiro Shimizu |
890ddd |
if (!m_active || !vi || !m_strokeRef) {
|
|
Toshihiro Shimizu |
890ddd |
delete m_undo;
|
|
Toshihiro Shimizu |
890ddd |
m_undo = 0;
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_range.second = m_strokeRef->getW(pos);
|
|
Toshihiro Shimizu |
890ddd |
m_cursor = m_strokeRef->getThickPoint(m_range.second);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double v0 = tmin(m_range.first, m_range.second);
|
|
Toshihiro Shimizu |
890ddd |
double v1 = tmax(m_range.first, m_range.second);
|
|
Toshihiro Shimizu |
890ddd |
const double eps = 0.005;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (v1 - v0 < eps && !(m_strokeRef->isSelfLoop() && 1 - (v1 - v0) < eps)) {
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD point2 = m_strokeRef->getPoint(m_range.second);
|
|
Toshihiro Shimizu |
890ddd |
double tdist2 = tdistance2(m_beginPoint, point2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double pixelSize = getPixelSize();
|
|
Toshihiro Shimizu |
890ddd |
if (tdist2 < 100 * pixelSize * pixelSize) {
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double draggedStrokeLen = m_strokeRef->getLength(v0, v1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double totalStrokeLen = m_strokeRef->getLength();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool direction = !m_strokeRef->isSelfLoop() ||
|
|
Toshihiro Shimizu |
890ddd |
draggedStrokeLen < totalStrokeLen - draggedStrokeLen;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!direction) {
|
|
Toshihiro Shimizu |
890ddd |
draggedStrokeLen = totalStrokeLen - draggedStrokeLen;
|
|
Toshihiro Shimizu |
890ddd |
tswap(v0, v1);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// se la lunghezza della parte di stroke tra i due punti di inizio e fine drag
|
|
Toshihiro Shimizu |
890ddd |
// e' piu' del quadruplo della distanza tra i due punti, allora non si fa nulla perche'
|
|
Toshihiro Shimizu |
890ddd |
// molto probabilmente si sta facendo drag tra due punti vicini di una curva piu' lunga
|
|
Toshihiro Shimizu |
890ddd |
if ((draggedStrokeLen * draggedStrokeLen) > 16.0 * tdist2) {
|
|
Toshihiro Shimizu |
890ddd |
m_beginPoint = point2;
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
int maxCP = m_strokeRef->getControlPointCount() - 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//iCP0 is the control point index before v0 (or just on v0)
|
|
Toshihiro Shimizu |
890ddd |
int iCP0 = (int)(maxCP * v0);
|
|
Toshihiro Shimizu |
890ddd |
int iCP1 = m_strokeRef->getControlPointIndexAfterParameter(v1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (iCP0 > maxCP) {
|
|
Toshihiro Shimizu |
890ddd |
if (!direction)
|
|
Toshihiro Shimizu |
890ddd |
iCP0 = maxCP;
|
|
Toshihiro Shimizu |
890ddd |
else {
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (iCP1 > maxCP)
|
|
Toshihiro Shimizu |
890ddd |
iCP1 = maxCP;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (direction && (iCP1 - iCP0) < 2) {
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!direction && maxCP + 1 - (iCP1 - iCP0) < 3) {
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//*********************************************** point of no return **************************
|
|
Toshihiro Shimizu |
890ddd |
m_dragged = true;
|
|
Toshihiro Shimizu |
890ddd |
m_beginPoint = point2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!m_strokeRef->isSelfLoop()) {
|
|
Toshihiro Shimizu |
890ddd |
if (m_cpIndexMin > iCP0)
|
|
Toshihiro Shimizu |
890ddd |
m_cpIndexMin = iCP0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_cpIndexMax < iCP1)
|
|
Toshihiro Shimizu |
890ddd |
m_cpIndexMax = iCP1;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
if (m_cpIndexMin == m_strokeRef->getControlPointCount() && m_cpIndexMax == -1) {
|
|
Toshihiro Shimizu |
890ddd |
m_cpIndexMin = iCP0;
|
|
Toshihiro Shimizu |
890ddd |
m_cpIndexMax = iCP1;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
if (isIncluded(iCP0, m_cpIndexMin, m_cpIndexMax)) {
|
|
Toshihiro Shimizu |
890ddd |
if (!isIncluded(iCP1, m_cpIndexMin, m_cpIndexMax)) {
|
|
Toshihiro Shimizu |
890ddd |
m_cpIndexMax = iCP1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
} else if (isIncluded(iCP1, m_cpIndexMin, m_cpIndexMax)) {
|
|
Toshihiro Shimizu |
890ddd |
assert(!isIncluded(iCP0, m_cpIndexMin, m_cpIndexMax));
|
|
Toshihiro Shimizu |
890ddd |
m_cpIndexMin = iCP0;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
int sgn = tsign(m_range.second - m_range.first);
|
|
Toshihiro Shimizu |
890ddd |
if (!direction)
|
|
Toshihiro Shimizu |
890ddd |
sgn = -sgn;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
switch (sgn) {
|
|
Toshihiro Shimizu |
890ddd |
case 1:
|
|
Toshihiro Shimizu |
890ddd |
m_cpIndexMax = iCP1;
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case -1:
|
|
Toshihiro Shimizu |
890ddd |
m_cpIndexMin = iCP0;
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case 0:
|
|
Toshihiro Shimizu |
890ddd |
assert(0);
|
|
Toshihiro Shimizu |
890ddd |
default:
|
|
Toshihiro Shimizu |
890ddd |
assert(0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_range.first = m_range.second;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(m_cpIndexMin != m_cpIndexMax);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
v0 = m_strokeRef->getParameterAtControlPoint(iCP0);
|
|
Toshihiro Shimizu |
890ddd |
v1 = m_strokeRef->getParameterAtControlPoint(iCP1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//double smoothFactor = getApplication()->getVectorToolsParameters().getToolSize();
|
|
Toshihiro Shimizu |
890ddd |
//smoothFactor *= 0.01;
|
|
Toshihiro Shimizu |
890ddd |
//smoothFactor = (smoothFactor*smoothFactor*smoothFactor)*0.7;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const double smoothFactor = 0.08;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double wDistance = (direction) ? v1 - v0 : 1 - (v0 - v1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double smoothFP = smoothFactor / wDistance;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD pf0 = m_strokeRef->getControlPoint(iCP0) * smoothFP;
|
|
Toshihiro Shimizu |
890ddd |
TPointD pf1 = m_strokeRef->getControlPoint(iCP1) * smoothFP;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD appDPoint;
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint appThickPoint;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double oppSmoothFactor = 1.0 - smoothFactor;
|
|
Toshihiro Shimizu |
890ddd |
double vp, v1vp, vpv0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
i = (iCP0 == maxCP || (iCP0 == 0 && !direction)) ? 1 : iCP0 + 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (; i != iCP1;) {
|
|
Toshihiro Shimizu |
890ddd |
vp = m_strokeRef->getParameterAtControlPoint(i);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
appThickPoint = m_strokeRef->getControlPoint(i);
|
|
Toshihiro Shimizu |
890ddd |
appDPoint = appThickPoint;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
v1vp = v1 - vp;
|
|
Toshihiro Shimizu |
890ddd |
if (v1vp < 0) {
|
|
Toshihiro Shimizu |
890ddd |
if (!direction)
|
|
Toshihiro Shimizu |
890ddd |
v1vp += 1;
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
assert(0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
vpv0 = vp - v0;
|
|
Toshihiro Shimizu |
890ddd |
if (vpv0 < 0) {
|
|
Toshihiro Shimizu |
890ddd |
if (!direction)
|
|
Toshihiro Shimizu |
890ddd |
vpv0 += 1;
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
assert(0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(isAlmostZero(v1vp + vpv0 - wDistance));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(isAlmostZero((smoothFP * v1vp + smoothFP * vpv0) + oppSmoothFactor - 1.0));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_strokeRef->setControlPoint(i, TThickPoint(
|
|
Toshihiro Shimizu |
890ddd |
pf0 * v1vp +
|
|
Toshihiro Shimizu |
890ddd |
pf1 * vpv0 +
|
|
Toshihiro Shimizu |
890ddd |
appDPoint * oppSmoothFactor,
|
|
Toshihiro Shimizu |
890ddd |
appThickPoint.thick));
|
|
Toshihiro Shimizu |
890ddd |
// this is like
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// averageP = ( p0*(v1-vp)/(v1-v0) + p1*(vp-v0)/(v1-v0));
|
|
Toshihiro Shimizu |
890ddd |
// newCP(i) = oldCP(i)*(1-smoothFactor) + averageP*smoothFactor
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// but faster
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
i++;
|
|
Toshihiro Shimizu |
890ddd |
if (i == maxCP + 1) {
|
|
Toshihiro Shimizu |
890ddd |
m_strokeRef->setControlPoint(0, m_strokeRef->getControlPoint(maxCP));
|
|
Toshihiro Shimizu |
890ddd |
i = 1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_strokeRef->invalidate();
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
notifyImageChanged();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void leftButtonUp(const TPointD &pos, const TMouseEvent &)
|
|
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 |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TVectorImageP vi(getImage(true));
|
|
Toshihiro Shimizu |
890ddd |
if (!vi || !m_strokeRef || !m_dragged) {
|
|
Toshihiro Shimizu |
890ddd |
delete m_undo;
|
|
Toshihiro Shimizu |
890ddd |
m_undo = 0;
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker lock(vi->getMutex());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//TStroke *oldStroke = new TStroke(*(vi->getStroke(m_selectedStroke)));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
UINT cpCount = m_strokeRef->getControlPointCount();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_cpIndexMin &= ~1; // nearest even value less or equal to m_cpIndexMin
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_cpIndexMax & 1) //odd
|
|
Toshihiro Shimizu |
890ddd |
m_cpIndexMax++;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int i = 0;
|
|
Toshihiro Shimizu |
890ddd |
UINT count = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((m_cpIndexMin == 0 && (UINT)m_cpIndexMax == cpCount - 1) ||
|
|
Toshihiro Shimizu |
890ddd |
(m_cpIndexMin == m_cpIndexMax && m_strokeRef->isSelfLoop())) {
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
e' meglio rilevarli i corners.
|
|
Toshihiro Shimizu |
890ddd |
Tanto se hai appiattito abbastanza, se ne vanno da soli,
|
|
Toshihiro Shimizu |
890ddd |
senza lasciare ingrati compiti alla reuceControlPoints
|
|
Toshihiro Shimizu |
890ddd |
Altrimenti non si fa altro che aumentarli i punti di controllo
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
vector<int> corners;</int>
|
|
Toshihiro Shimizu |
890ddd |
corners.push_back(0);
|
|
Toshihiro Shimizu |
890ddd |
detectCorners(m_strokeRef, 45, corners);
|
|
Toshihiro Shimizu |
890ddd |
corners.push_back(m_strokeRef->getChunkCount());
|
|
Toshihiro Shimizu |
890ddd |
m_strokeRef->reduceControlPoints(2.0 * getPixelSize(), corners);
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
if (m_cpIndexMin < m_cpIndexMax) {
|
|
Toshihiro Shimizu |
890ddd |
vector<tthickpoint> hitPoints(m_cpIndexMax - m_cpIndexMin + 1);</tthickpoint>
|
|
Toshihiro Shimizu |
890ddd |
count = 0;
|
|
Toshihiro Shimizu |
890ddd |
for (i = m_cpIndexMin; i <= m_cpIndexMax; i++) {
|
|
Toshihiro Shimizu |
890ddd |
hitPoints[count++] = m_strokeRef->getControlPoint(i);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
TStroke *newStroke = new TStroke(hitPoints);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
vector<int> corners;</int>
|
|
Toshihiro Shimizu |
890ddd |
corners.push_back(0);
|
|
Toshihiro Shimizu |
890ddd |
detectCorners(newStroke, 45, corners);
|
|
Toshihiro Shimizu |
890ddd |
corners.push_back(newStroke->getChunkCount());
|
|
Toshihiro Shimizu |
890ddd |
newStroke->reduceControlPoints(2.0 * getPixelSize(), corners);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
hitPoints.resize(m_cpIndexMin + newStroke->getControlPointCount() + cpCount - 1 - m_cpIndexMax);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
count = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < m_cpIndexMin; i++) {
|
|
Toshihiro Shimizu |
890ddd |
hitPoints[count++] = m_strokeRef->getControlPoint(i);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < newStroke->getControlPointCount(); i++) {
|
|
Toshihiro Shimizu |
890ddd |
hitPoints[count++] = newStroke->getControlPoint(i);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = m_cpIndexMax + 1; i < (int)cpCount; i++) {
|
|
Toshihiro Shimizu |
890ddd |
hitPoints[count++] = m_strokeRef->getControlPoint(i);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_strokeRef->reshape(&hitPoints[0], hitPoints.size());
|
|
Toshihiro Shimizu |
890ddd |
delete newStroke;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
assert(m_cpIndexMin != m_cpIndexMax);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
vector<tthickpoint> hitPoints(cpCount - m_cpIndexMin);</tthickpoint>
|
|
Toshihiro Shimizu |
890ddd |
count = 0;
|
|
Toshihiro Shimizu |
890ddd |
for (i = m_cpIndexMin; i < (int)cpCount; i++) {
|
|
Toshihiro Shimizu |
890ddd |
hitPoints[count++] = m_strokeRef->getControlPoint(i);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
TStroke *newStroke1 = new TStroke(hitPoints);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
vector<int> corners;</int>
|
|
Toshihiro Shimizu |
890ddd |
corners.push_back(0);
|
|
Toshihiro Shimizu |
890ddd |
detectCorners(newStroke1, 45, corners);
|
|
Toshihiro Shimizu |
890ddd |
corners.push_back(newStroke1->getChunkCount());
|
|
Toshihiro Shimizu |
890ddd |
newStroke1->reduceControlPoints(2.0 * getPixelSize(), corners);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
hitPoints.resize(m_cpIndexMax + 1);
|
|
Toshihiro Shimizu |
890ddd |
count = 0;
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i <= m_cpIndexMax; i++) {
|
|
Toshihiro Shimizu |
890ddd |
hitPoints[count++] = m_strokeRef->getControlPoint(i);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
TStroke *newStroke2 = new TStroke(hitPoints);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
corners.clear();
|
|
Toshihiro Shimizu |
890ddd |
corners.push_back(0);
|
|
Toshihiro Shimizu |
890ddd |
detectCorners(newStroke2, 45, corners);
|
|
Toshihiro Shimizu |
890ddd |
corners.push_back(newStroke2->getChunkCount());
|
|
Toshihiro Shimizu |
890ddd |
newStroke2->reduceControlPoints(2.0 * getPixelSize(), corners);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
hitPoints.resize(
|
|
Toshihiro Shimizu |
890ddd |
newStroke1->getControlPointCount() +
|
|
Toshihiro Shimizu |
890ddd |
newStroke2->getControlPointCount() +
|
|
Toshihiro Shimizu |
890ddd |
m_cpIndexMin - m_cpIndexMax - 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
count = 0;
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < newStroke2->getControlPointCount(); i++) {
|
|
Toshihiro Shimizu |
890ddd |
hitPoints[count++] = newStroke2->getControlPoint(i);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
for (i = m_cpIndexMax + 1; i < m_cpIndexMin; i++) {
|
|
Toshihiro Shimizu |
890ddd |
hitPoints[count++] = m_strokeRef->getControlPoint(i);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < newStroke1->getControlPointCount(); i++) {
|
|
Toshihiro Shimizu |
890ddd |
hitPoints[count++] = newStroke1->getControlPoint(i);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_strokeRef->reshape(&hitPoints[0], hitPoints.size());
|
|
Toshihiro Shimizu |
890ddd |
delete newStroke1;
|
|
Toshihiro Shimizu |
890ddd |
delete newStroke2;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_dragged = false;
|
|
Toshihiro Shimizu |
890ddd |
assert(m_undo);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(m_oldStroke);
|
|
Toshihiro Shimizu |
890ddd |
vi->notifyChangedStrokes(m_selectedStroke, m_oldStroke);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TUndoManager::manager()->add(m_undo);
|
|
Toshihiro Shimizu |
890ddd |
m_undo = 0;
|
|
Toshihiro Shimizu |
890ddd |
delete m_oldStroke;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void invalidateCursorArea()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double r = m_cursor.thick + 6;
|
|
Toshihiro Shimizu |
890ddd |
TPointD d(r, r);
|
|
Toshihiro Shimizu |
890ddd |
invalidate(TRectD(m_cursor - d, m_cursor + d));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void mouseMove(const TPointD &pos, const TMouseEvent &e)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TVectorImageP vi = TImageP(getImage(true));
|
|
Toshihiro Shimizu |
890ddd |
if (!vi) {
|
|
Toshihiro Shimizu |
890ddd |
m_draw = false;
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// select nearest stroke and finds its parameter
|
|
Toshihiro Shimizu |
890ddd |
double dist, pW;
|
|
Toshihiro Shimizu |
890ddd |
UINT stroke;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (vi->getNearestStroke(pos, pW, stroke, dist)) {
|
|
Toshihiro Shimizu |
890ddd |
m_draw = true;
|
|
Toshihiro Shimizu |
890ddd |
TStroke *strokeRef = vi->getStroke(stroke);
|
|
Toshihiro Shimizu |
890ddd |
m_cursor = strokeRef->getThickPoint(pW);
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
m_draw = false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool moveCursor(const TPointD &pos)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void onActivate()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// getApplication()->editImageOrSpline();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void onLeave()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_draw = false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int getCursorId() const { return m_cursorId; }
|
|
Toshihiro Shimizu |
890ddd |
void onEnter()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_draw = true;
|
|
Toshihiro Shimizu |
890ddd |
if ((TVectorImageP)getImage(false))
|
|
Toshihiro Shimizu |
890ddd |
m_cursorId = ToolCursor::IronCursor;
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
m_cursorId = ToolCursor::CURSOR_NO;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} ironTool;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef _DEBUG
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void drawPoint(const TPointD &p, double pixelSize)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double sizeX = pixelSize;
|
|
Toshihiro Shimizu |
890ddd |
double sizeY = pixelSize;
|
|
Toshihiro Shimizu |
890ddd |
glBegin(GL_QUADS);
|
|
Toshihiro Shimizu |
890ddd |
glVertex2d(p.x - sizeX, p.y - sizeY);
|
|
Toshihiro Shimizu |
890ddd |
glVertex2d(p.x - sizeX, p.y + sizeY);
|
|
Toshihiro Shimizu |
890ddd |
glVertex2d(p.x + sizeX, p.y + sizeY);
|
|
Toshihiro Shimizu |
890ddd |
glVertex2d(p.x + sizeX, p.y - sizeY);
|
|
Toshihiro Shimizu |
890ddd |
glEnd();
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void drawControlPoints(const TStroke *&stroke, double pixelSize)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int n = stroke->getChunkCount();
|
|
Toshihiro Shimizu |
890ddd |
int i = 0;
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < n; ++i) {
|
|
Toshihiro Shimizu |
890ddd |
const TThickQuadratic *chunk = stroke->getChunk(i);
|
|
Toshihiro Shimizu |
890ddd |
TPointD p0 = chunk->getP0();
|
|
Toshihiro Shimizu |
890ddd |
TPointD p1 = chunk->getP1();
|
|
Toshihiro Shimizu |
890ddd |
glColor3d(1.0, 0.0, 0.0);
|
|
Toshihiro Shimizu |
890ddd |
drawPoint(p0, pixelSize);
|
|
Toshihiro Shimizu |
890ddd |
glColor3d(1.0, 1.0, 1.0);
|
|
Toshihiro Shimizu |
890ddd |
drawPoint(p1, pixelSize);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
const TThickQuadratic *chunk = stroke->getChunk(n - 1);
|
|
Toshihiro Shimizu |
890ddd |
glColor3d(1.0, 0.0, 0.0);
|
|
Toshihiro Shimizu |
890ddd |
TPointD p2 = chunk->getP2();
|
|
Toshihiro Shimizu |
890ddd |
drawPoint(p2, pixelSize);
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
// end solo per debug
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//TTool *getIronTool() {return &ironTool;}
|