|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tvectorgl.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tgl.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tpalette.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tproperty.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tthreadmessage.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tvectorimage.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "drawutil.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcurveutil.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstroke.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstrokeutil.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tvectorrenderdata.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstrokedeformations.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tmathutil.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Toonz includes
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tobjecthandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/txshlevelhandle.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//TnzTools includes
|
|
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 |
//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 |
//*****************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// PumpTool declaration
|
|
Toshihiro Shimizu |
890ddd |
//*****************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class PumpTool : public TTool
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
Q_DECLARE_TR_FUNCTIONS(PumpTool)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int m_strokeStyleId, m_strokeIndex; //!< Edited stroke indices
|
|
Toshihiro Shimizu |
890ddd |
TStroke *m_inStroke, *m_outStroke; //!< Input/Output strokes
|
|
Shinya Kitaoka |
3bfa54 |
std::vector<tstroke *=""> m_splitStrokes; //!< Merging these, m_inStroke is reformed</tstroke>
|
|
Toshihiro Shimizu |
890ddd |
int m_stroke1Idx, m_stroke2Idx; //!< Indices of deformed strokes among split ones
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TUndo *m_undo; //!< Undo to be added upon non-trivial button up
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double m_actionW; //!< The action center stroke parameter
|
|
Toshihiro Shimizu |
890ddd |
double m_actionS1, m_actionS2; //!< Action center length in m_stroke
|
|
Toshihiro Shimizu |
890ddd |
double m_actionRadius; //!< Tool action radius in curve length
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
3bfa54 |
std::vector<double> m_splitPars; //!< Split parameters for action localization</double>
|
|
Shinya Kitaoka |
3bfa54 |
std::vector<double> m_cpLenDiff1, m_cpLenDiff2; //!< Distorted CPs' length distances from action center</double>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool m_active; //!< Whether a stroke is currently being edited
|
|
Toshihiro Shimizu |
890ddd |
bool m_enabled; //!< Tells whether the image allows editing
|
|
Toshihiro Shimizu |
890ddd |
bool m_cursorEnabled; //!< Whether the 'pump preview cursor' can be seen
|
|
Toshihiro Shimizu |
890ddd |
bool m_draw; //!< Should be removed...?
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD m_oldPoint, m_downPoint; //!< Mouse positions upon editing
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint m_cursor; //!< Pump preview cursor data
|
|
Toshihiro Shimizu |
890ddd |
int m_cursorId;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double m_errorTol; //!< Allowed approximation error during edit
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TDoubleProperty m_toolSize;
|
|
Toshihiro Shimizu |
890ddd |
TIntProperty m_accuracy;
|
|
Toshihiro Shimizu |
890ddd |
TPropertyGroup m_prop;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
PumpTool()
|
|
Toshihiro Shimizu |
890ddd |
: TTool("T_Pump"), m_active(false), m_actionW(0), m_strokeIndex((std::numeric_limits<uint>::max)()), m_inStroke(0), m_outStroke(0), m_stroke1Idx(-1), m_stroke2Idx(-1), m_cursorEnabled(false), m_cursorId(ToolCursor::PumpCursor), m_actionRadius(1), m_draw(false), m_undo(0), m_toolSize("Size:", 1, 100, 20), m_accuracy("Accuracy:", 0, 100, 40), m_enabled(false)</uint>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
bind(TTool::VectorImage);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_splitPars.resize(2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_prop.bind(m_toolSize);
|
|
Toshihiro Shimizu |
890ddd |
m_prop.bind(m_accuracy);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToolType getToolType() const { return TTool::LevelWriteTool; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPropertyGroup *getProperties(int targetType) { return &m_prop; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void updateTranslation()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_toolSize.setQStringName(tr("Size:"));
|
|
Toshihiro Shimizu |
890ddd |
m_accuracy.setQStringName(tr("Accuracy:"));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void onEnter();
|
|
Toshihiro Shimizu |
890ddd |
void onLeave();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void draw();
|
|
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 &e);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void mouseMove(const TPointD &pos, const TMouseEvent &e);
|
|
Toshihiro Shimizu |
890ddd |
bool moveCursor(const TPointD &pos);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int getCursorId() const { return m_cursorId; }
|
|
Toshihiro Shimizu |
890ddd |
void invalidateCursorArea();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void onDeactivate();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Toshihiro Shimizu |
890ddd |
double actionRadius(double strokeLength);
|
|
Toshihiro Shimizu |
890ddd |
void splitStroke(TStroke *s);
|
|
Toshihiro Shimizu |
890ddd |
TStroke *mergeStrokes(const std::vector<tstroke *=""> &strokes);</tstroke>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} PumpToolInstance;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//*****************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// PumpTool implementation
|
|
Toshihiro Shimizu |
890ddd |
//*****************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PumpTool::onEnter()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_draw = true;
|
|
Toshihiro Shimizu |
890ddd |
if (TTool::getApplication()->getCurrentObject()->isSpline() ||
|
|
Toshihiro Shimizu |
890ddd |
!(TVectorImageP)getImage(false)) {
|
|
Toshihiro Shimizu |
890ddd |
m_enabled = false;
|
|
Toshihiro Shimizu |
890ddd |
m_cursorId = ToolCursor::CURSOR_NO;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
m_enabled = true;
|
|
Toshihiro Shimizu |
890ddd |
m_cursorId = ToolCursor::PumpCursor;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PumpTool::draw()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!m_draw || !m_enabled)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TVectorImageP vi = TImageP(getImage(false));
|
|
Toshihiro Shimizu |
890ddd |
if (!vi)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker lock(vi->getMutex());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPalette *palette = vi->getPalette();
|
|
Toshihiro Shimizu |
890ddd |
assert(palette);
|
|
Toshihiro Shimizu |
890ddd |
if (m_active) {
|
|
Toshihiro Shimizu |
890ddd |
//Editing with the tool
|
|
Toshihiro Shimizu |
890ddd |
assert(m_outStroke);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRectD bboxD(m_outStroke->getBBox());
|
|
Toshihiro Shimizu |
890ddd |
TRect bbox(tfloor(bboxD.x0), tfloor(bboxD.y0), tceil(bboxD.x1) - 1, tceil(bboxD.y1) - 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tglDraw(TVectorRenderData(TAffine(), bbox, palette, 0, true), m_outStroke);
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
//Hovering
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double w, dist;
|
|
Toshihiro Shimizu |
890ddd |
UINT index;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_cursorEnabled) {
|
|
Toshihiro Shimizu |
890ddd |
//Draw cursor
|
|
Toshihiro Shimizu |
890ddd |
glColor3d(1.0, 0.0, 1.0);
|
|
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 |
if (vi->getNearestStroke(m_cursor, w, index, dist, true)) {
|
|
Toshihiro Shimizu |
890ddd |
TStroke *stroke = vi->getStroke(index);
|
|
Toshihiro Shimizu |
890ddd |
double totalLen = stroke->getLength();
|
|
Toshihiro Shimizu |
890ddd |
double actionLen = actionRadius(totalLen);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tglColor(TPixel32::Red);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (totalLen < actionLen || (stroke->isSelfLoop() && totalLen < actionLen + actionLen))
|
|
Toshihiro Shimizu |
890ddd |
drawStrokeCenterline(*stroke, getPixelSize());
|
|
Toshihiro Shimizu |
890ddd |
else {
|
|
Toshihiro Shimizu |
890ddd |
int i, chunckIndex1, chunckIndex2;
|
|
Toshihiro Shimizu |
890ddd |
double t, t1, t2, w1, w2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double len = stroke->getLength(w);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double len1 = len - actionLen;
|
|
Toshihiro Shimizu |
890ddd |
if (len1 < 0)
|
|
Toshihiro Shimizu |
890ddd |
if (stroke->isSelfLoop())
|
|
Toshihiro Shimizu |
890ddd |
len1 += totalLen;
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
len1 = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double len2 = len + actionLen;
|
|
Toshihiro Shimizu |
890ddd |
if (len2 > totalLen)
|
|
Toshihiro Shimizu |
890ddd |
if (stroke->isSelfLoop())
|
|
Toshihiro Shimizu |
890ddd |
len2 -= totalLen;
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
len2 = totalLen;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
w1 = stroke->getParameterAtLength(len1);
|
|
Toshihiro Shimizu |
890ddd |
w2 = stroke->getParameterAtLength(len2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int chunkCount = stroke->getChunkCount();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
stroke->getChunkAndT(w1, chunckIndex1, t1);
|
|
Toshihiro Shimizu |
890ddd |
stroke->getChunkAndT(w2, chunckIndex2, t2);
|
|
Toshihiro Shimizu |
890ddd |
double step;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TThickQuadratic *q = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
glBegin(GL_LINE_STRIP);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
q = stroke->getChunk(chunckIndex1);
|
|
Toshihiro Shimizu |
890ddd |
step = computeStep(*q, getPixelSize());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (chunckIndex1 == chunckIndex2 && t1 < t2) {
|
|
Toshihiro Shimizu |
890ddd |
for (t = t1; t < t2; t += step)
|
|
Toshihiro Shimizu |
890ddd |
tglVertex(q->getPoint(t));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tglVertex(stroke->getPoint(w2));
|
|
Toshihiro Shimizu |
890ddd |
glEnd();
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (t = t1; t < 1; t += step)
|
|
Toshihiro Shimizu |
890ddd |
tglVertex(q->getPoint(t));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = chunckIndex1 + 1; i != chunckIndex2; i++) {
|
|
Toshihiro Shimizu |
890ddd |
if (i == chunkCount)
|
|
Toshihiro Shimizu |
890ddd |
i = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (i == chunckIndex2)
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
q = stroke->getChunk(i);
|
|
Toshihiro Shimizu |
890ddd |
step = computeStep(*q, getPixelSize());
|
|
Toshihiro Shimizu |
890ddd |
for (t = 0; t < 1; t += step)
|
|
Toshihiro Shimizu |
890ddd |
tglVertex(q->getPoint(t));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
q = stroke->getChunk(chunckIndex2);
|
|
Toshihiro Shimizu |
890ddd |
step = computeStep(*q, getPixelSize());
|
|
Toshihiro Shimizu |
890ddd |
for (t = 0; t < t2; t += step)
|
|
Toshihiro Shimizu |
890ddd |
tglVertex(q->getPoint(t));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tglVertex(stroke->getPoint(w2));
|
|
Toshihiro Shimizu |
890ddd |
|
|
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 |
|
|
Toshihiro Shimizu |
890ddd |
void PumpTool::leftButtonDown(const TPointD &pos, const TMouseEvent &)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_active || !m_enabled)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(m_undo == 0);
|
|
Toshihiro Shimizu |
890ddd |
m_active = false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TVectorImageP vi(getImage(true));
|
|
Toshihiro Shimizu |
890ddd |
if (!vi)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker lock(vi->getMutex());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// set current point and init parameters
|
|
Toshihiro Shimizu |
890ddd |
m_oldPoint = pos;
|
|
Toshihiro Shimizu |
890ddd |
m_downPoint = pos;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_inStroke = m_outStroke = 0;
|
|
Toshihiro Shimizu |
890ddd |
m_stroke1Idx = m_stroke2Idx = -1;
|
|
Toshihiro Shimizu |
890ddd |
m_splitPars[0] = m_splitPars[1] = -2;
|
|
Toshihiro Shimizu |
890ddd |
m_actionW = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_errorTol = (1.0 - 0.01 * m_accuracy.getValue()) * getPixelSize();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double dist2 = 0.0;
|
|
Toshihiro Shimizu |
890ddd |
int cpCount;
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
UINT index;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (vi->getNearestStroke(pos, m_actionW, index, dist2)) {
|
|
Toshihiro Shimizu |
890ddd |
//A stroke near the pressed point was found - modify it
|
|
Toshihiro Shimizu |
890ddd |
m_active = true;
|
|
Toshihiro Shimizu |
890ddd |
m_strokeIndex = index;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_inStroke = vi->getStroke(m_strokeIndex);
|
|
Toshihiro Shimizu |
890ddd |
m_outStroke = new TStroke(*m_inStroke);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double totalLength = m_inStroke->getLength();
|
|
Toshihiro Shimizu |
890ddd |
TXshSimpleLevel *sl = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
|
|
Toshihiro Shimizu |
890ddd |
assert(sl);
|
|
Toshihiro Shimizu |
890ddd |
TFrameId id = getCurrentFid();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Allocate the modification undo - will be assigned to the undo manager on mouse release
|
|
Toshihiro Shimizu |
890ddd |
m_undo = new UndoModifyStrokeAndPaint(sl, id, m_strokeIndex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Set the stroke's style to 'none'. This is needed to make the original stroke transparent,
|
|
Toshihiro Shimizu |
890ddd |
//while the deformed one is shown at its place.
|
|
Toshihiro Shimizu |
890ddd |
m_strokeStyleId = m_inStroke->getStyle();
|
|
Toshihiro Shimizu |
890ddd |
m_inStroke->setStyle(0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (totalLength <= 0.0) {
|
|
Toshihiro Shimizu |
890ddd |
//Single point case
|
|
Toshihiro Shimizu |
890ddd |
cpCount = m_inStroke->getControlPointCount();
|
|
Toshihiro Shimizu |
890ddd |
m_cpLenDiff1.resize(cpCount);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < cpCount; i++)
|
|
Toshihiro Shimizu |
890ddd |
m_cpLenDiff1[i] = 0.0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_splitStrokes.resize(1);
|
|
Toshihiro Shimizu |
890ddd |
m_splitStrokes[0] = new TStroke(*m_inStroke);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_stroke1Idx = 0;
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
//Common strokes - split the stroke according to deformation requirements
|
|
Toshihiro Shimizu |
890ddd |
splitStroke(m_inStroke);
|
|
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 PumpTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!m_active || !m_enabled)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TVectorImageP vi(getImage(true));
|
|
Toshihiro Shimizu |
890ddd |
if (!vi || !m_outStroke)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker lock(vi->getMutex());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Revert current deformation, recovering the one from button press
|
|
Toshihiro Shimizu |
890ddd |
delete m_outStroke;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Retrieve cursor's vertical displacement
|
|
Toshihiro Shimizu |
890ddd |
TPointD delta = TPointD(0, (pos - m_downPoint).y);
|
|
Toshihiro Shimizu |
890ddd |
int deltaSign = tsign(delta.y);
|
|
Toshihiro Shimizu |
890ddd |
if (deltaSign == 0) {
|
|
Toshihiro Shimizu |
890ddd |
//Use a copy of the original stroke
|
|
Toshihiro Shimizu |
890ddd |
m_outStroke = new TStroke(*m_inStroke);
|
|
Toshihiro Shimizu |
890ddd |
m_outStroke->setStyle(m_strokeStyleId);
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Build deformation upon the original stroke pieces
|
|
Toshihiro Shimizu |
890ddd |
TStroke *stroke1 = 0, *stroke2 = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
stroke1 = new TStroke(*m_splitStrokes[m_stroke1Idx]);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Deform stroke1
|
|
Toshihiro Shimizu |
890ddd |
TStrokeThicknessDeformation deformer(stroke1, delta, m_actionS1, m_actionRadius, deltaSign);
|
|
Toshihiro Shimizu |
890ddd |
modifyThickness(*stroke1, deformer, m_cpLenDiff1, deltaSign < 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_stroke2Idx >= 0) {
|
|
Toshihiro Shimizu |
890ddd |
//Deform stroke2
|
|
Toshihiro Shimizu |
890ddd |
stroke2 = new TStroke(*m_splitStrokes[m_stroke2Idx]);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TStrokeThicknessDeformation deformer2(stroke2, delta, m_actionS2, m_actionRadius, deltaSign);
|
|
Toshihiro Shimizu |
890ddd |
modifyThickness(*stroke2, deformer2, m_cpLenDiff2, deltaSign < 0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Apply deformation
|
|
Toshihiro Shimizu |
890ddd |
std::vector<tstroke *=""> splitStrokesCopy(m_splitStrokes);</tstroke>
|
|
Toshihiro Shimizu |
890ddd |
splitStrokesCopy[m_stroke1Idx] = stroke1;
|
|
Toshihiro Shimizu |
890ddd |
if (stroke2)
|
|
Toshihiro Shimizu |
890ddd |
splitStrokesCopy[m_stroke2Idx] = stroke2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_outStroke = mergeStrokes(splitStrokesCopy);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
delete stroke1;
|
|
Toshihiro Shimizu |
890ddd |
delete stroke2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PumpTool::leftButtonUp(const TPointD &pos, const TMouseEvent &)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TVectorImageP vi;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!m_active || !m_enabled)
|
|
Toshihiro Shimizu |
890ddd |
goto cleanup;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
vi = TVectorImageP(getImage(true));
|
|
Toshihiro Shimizu |
890ddd |
if (!vi)
|
|
Toshihiro Shimizu |
890ddd |
goto cleanup;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_active = false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker lock(vi->getMutex());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Reset cursor data
|
|
Toshihiro Shimizu |
890ddd |
double t;
|
|
Toshihiro Shimizu |
890ddd |
UINT index;
|
|
Toshihiro Shimizu |
890ddd |
double dist2;
|
|
Toshihiro Shimizu |
890ddd |
if (vi->getNearestStroke(pos, t, index, dist2)) {
|
|
Toshihiro Shimizu |
890ddd |
TStroke *nearestStroke = vi->getStroke(index);
|
|
Toshihiro Shimizu |
890ddd |
if (nearestStroke)
|
|
Toshihiro Shimizu |
890ddd |
m_cursor = nearestStroke->getThickPoint(t);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_outStroke &&
|
|
Toshihiro Shimizu |
890ddd |
!areAlmostEqual(m_downPoint, pos, PickRadius * getPixelSize())) {
|
|
Toshihiro Shimizu |
890ddd |
//Accept action
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Clone input stroke - it is someway needed by the stroke change notifier... I wonder why...
|
|
Toshihiro Shimizu |
890ddd |
TStroke *oldStroke = new TStroke(*m_inStroke);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_outStroke->swap(*m_inStroke);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_inStroke->invalidate();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
delete m_outStroke;
|
|
Toshihiro Shimizu |
890ddd |
m_outStroke = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(m_undo);
|
|
Toshihiro Shimizu |
890ddd |
TUndoManager::manager()->add(m_undo);
|
|
Toshihiro Shimizu |
890ddd |
m_undo = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
vi->notifyChangedStrokes(m_strokeIndex, oldStroke);
|
|
Toshihiro Shimizu |
890ddd |
notifyImageChanged();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
delete oldStroke;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
cleanup:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_inStroke)
|
|
Toshihiro Shimizu |
890ddd |
m_inStroke->setStyle(m_strokeStyleId); //Make the image stroke visible again
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_strokeIndex = m_strokeStyleId = -1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
clearPointerContainer(m_splitStrokes);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
delete m_outStroke;
|
|
Toshihiro Shimizu |
890ddd |
m_inStroke = m_outStroke = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
delete m_undo;
|
|
Toshihiro Shimizu |
890ddd |
m_undo = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PumpTool::invalidateCursorArea()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double r = m_cursor.thick + 6;
|
|
Toshihiro Shimizu |
890ddd |
TPointD d(r, r);
|
|
Toshihiro Shimizu |
890ddd |
invalidate(TRectD(m_cursor - d, m_cursor + d));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PumpTool::mouseMove(const TPointD &pos, const TMouseEvent &e)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_active || !m_enabled)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Cursor preview updates on 3-pixel steps
|
|
Toshihiro Shimizu |
890ddd |
if (tdistance2(pos, m_oldPoint) < 9.0 * sq(getPixelSize()))
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!m_draw)
|
|
Toshihiro Shimizu |
890ddd |
m_draw = true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_oldPoint = pos;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (moveCursor(pos)) {
|
|
Toshihiro Shimizu |
890ddd |
m_cursorEnabled = true;
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
m_cursorEnabled = false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool PumpTool::moveCursor(const TPointD &pos)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TVectorImageP vi(getImage(false));
|
|
Toshihiro Shimizu |
890ddd |
if (vi) {
|
|
Toshihiro Shimizu |
890ddd |
double t;
|
|
Toshihiro Shimizu |
890ddd |
UINT index;
|
|
Toshihiro Shimizu |
890ddd |
double dist2;
|
|
Toshihiro Shimizu |
890ddd |
if (vi->getNearestStroke(pos, t, index, dist2)) {
|
|
Toshihiro Shimizu |
890ddd |
TStroke *stroke = vi->getStroke(index);
|
|
Toshihiro Shimizu |
890ddd |
if (stroke) {
|
|
Toshihiro Shimizu |
890ddd |
m_cursor = stroke->getThickPoint(t);
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PumpTool::onDeactivate()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_draw = false;
|
|
Toshihiro Shimizu |
890ddd |
if (m_active) {
|
|
Toshihiro Shimizu |
890ddd |
m_active = false;
|
|
Toshihiro Shimizu |
890ddd |
TVectorImageP vi(getImage(true));
|
|
Toshihiro Shimizu |
890ddd |
assert(!!vi && m_outStroke);
|
|
Toshihiro Shimizu |
890ddd |
if (!vi || !m_outStroke)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
clearPointerContainer(m_splitStrokes);
|
|
Toshihiro Shimizu |
890ddd |
if (m_splitPars[0] == -1) {
|
|
Toshihiro Shimizu |
890ddd |
delete m_outStroke;
|
|
Toshihiro Shimizu |
890ddd |
m_outStroke = 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// restore previous style
|
|
Toshihiro Shimizu |
890ddd |
assert(m_strokeIndex >= 0);
|
|
Toshihiro Shimizu |
890ddd |
if (m_strokeIndex >= 0) {
|
|
Toshihiro Shimizu |
890ddd |
TStroke *stroke = vi->getStroke(m_strokeIndex);
|
|
Toshihiro Shimizu |
890ddd |
stroke->setStyle(m_strokeStyleId);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(m_undo);
|
|
Toshihiro Shimizu |
890ddd |
delete m_undo;
|
|
Toshihiro Shimizu |
890ddd |
m_undo = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_strokeIndex = -1;
|
|
Toshihiro Shimizu |
890ddd |
m_outStroke = 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PumpTool::onLeave()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!m_active)
|
|
Toshihiro Shimizu |
890ddd |
m_draw = false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//*****************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// PumpTool privates
|
|
Toshihiro Shimizu |
890ddd |
//*****************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double PumpTool::actionRadius(double strokeLength)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Shinya Kitaoka |
12c444 |
double toolSize = std::max(m_toolSize.getValue(), 5.0);
|
|
Toshihiro Shimizu |
890ddd |
double toolPercent = toolSize * 0.01;
|
|
Toshihiro Shimizu |
890ddd |
double interpolationVal = pow(toolPercent, 5);
|
|
Toshihiro Shimizu |
890ddd |
double indipendentValue = 7.0 * toolSize;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double actionRadius = (indipendentValue) * (1.0 - interpolationVal) +
|
|
Toshihiro Shimizu |
890ddd |
(strokeLength * toolPercent) * interpolationVal;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
12c444 |
return std::max(actionRadius, indipendentValue);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
Edited strokes are split near the corresponding editing position, in order
|
|
Toshihiro Shimizu |
890ddd |
to localize stroke manipulation.
|
|
Toshihiro Shimizu |
890ddd |
Only the localized part of the stroke will receive CP increase and thickness
|
|
Toshihiro Shimizu |
890ddd |
tuning needed for the tool action.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
void PumpTool::splitStroke(TStroke *s)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(m_splitStrokes.empty());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TStroke *stroke1 = 0, *stroke2 = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Build the action radius
|
|
Toshihiro Shimizu |
890ddd |
double totalLength = s->getLength();
|
|
Toshihiro Shimizu |
890ddd |
m_actionRadius = actionRadius(totalLength);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Get the length at selected point and build the split (length) positions
|
|
Toshihiro Shimizu |
890ddd |
m_actionS1 = s->getLength(m_actionW);
|
|
Toshihiro Shimizu |
890ddd |
double startLen = m_actionS1 - m_actionRadius;
|
|
Toshihiro Shimizu |
890ddd |
double endLen = m_actionS1 + m_actionRadius;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Now, perform splitting
|
|
Toshihiro Shimizu |
890ddd |
int i, cpCount;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((startLen <= 0 && endLen >= totalLength) ||
|
|
Toshihiro Shimizu |
890ddd |
(s->isSelfLoop() && totalLength < (m_actionRadius + m_actionRadius))) {
|
|
Toshihiro Shimizu |
890ddd |
//The whole stroke is included in the action - no split
|
|
Toshihiro Shimizu |
890ddd |
m_splitStrokes.resize(1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_splitPars[0] = -1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_splitStrokes[0] = new TStroke(*s);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_stroke1Idx = 0;
|
|
Toshihiro Shimizu |
890ddd |
stroke1 = m_splitStrokes[m_stroke1Idx];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TStrokeThicknessDeformation deformer(s, m_actionS1, m_actionRadius);
|
|
Toshihiro Shimizu |
890ddd |
increaseControlPoints(*stroke1, deformer, getPixelSize());
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
if (!s->isSelfLoop() || (startLen >= 0.0 && endLen <= totalLength)) {
|
|
Toshihiro Shimizu |
890ddd |
//Regular split positions, in the [0.0, totalLength] range.
|
|
Toshihiro Shimizu |
890ddd |
//Split points at extremities are dealt.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
12c444 |
m_splitPars[0] = s->getParameterAtLength(std::max(startLen, 0.0)); //Crop in the open case
|
|
Shinya Kitaoka |
12c444 |
m_splitPars[1] = s->getParameterAtLength(std::min(endLen, totalLength));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_splitPars[0] == 0.0) // the "&& m_splitPars[0] == totalLength" was dealt outside
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_splitStrokes.resize(2);
|
|
Toshihiro Shimizu |
890ddd |
m_splitStrokes[0] = new TStroke;
|
|
Toshihiro Shimizu |
890ddd |
m_splitStrokes[1] = new TStroke;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
s->split(m_splitPars[1], *(m_splitStrokes[0]), *(m_splitStrokes[1]));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_stroke1Idx = 0;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
if (m_splitPars[1] == 1.0) {
|
|
Toshihiro Shimizu |
890ddd |
m_splitStrokes.resize(2);
|
|
Toshihiro Shimizu |
890ddd |
m_splitStrokes[0] = new TStroke;
|
|
Toshihiro Shimizu |
890ddd |
m_splitStrokes[1] = new TStroke;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
s->split(m_splitPars[0], *(m_splitStrokes[0]), *(m_splitStrokes[1]));
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
::splitStroke(*s, m_splitPars, m_splitStrokes);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_stroke1Idx = 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Update the edit point to refer to the central stroke piece
|
|
Toshihiro Shimizu |
890ddd |
m_actionS1 -= m_splitStrokes[0]->getLength();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
stroke1 = m_splitStrokes[m_stroke1Idx];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Apply deformation to the middle piece
|
|
Toshihiro Shimizu |
890ddd |
TStrokeThicknessDeformation deformer(stroke1, m_actionS1, m_actionRadius);
|
|
Toshihiro Shimizu |
890ddd |
increaseControlPoints(*stroke1, deformer, getPixelSize());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_actionS2 = 0;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
//Circular 'overflow' case - (exactly) one split point is outside the regular scope.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Since the action diameter is < totalLength, these cases are mutually exclusive.
|
|
Toshihiro Shimizu |
890ddd |
if (startLen < 0)
|
|
Toshihiro Shimizu |
890ddd |
startLen += totalLength;
|
|
Toshihiro Shimizu |
890ddd |
else {
|
|
Toshihiro Shimizu |
890ddd |
endLen -= totalLength;
|
|
Toshihiro Shimizu |
890ddd |
m_actionS1 -= totalLength;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//The deformation must be applied in two distinct strokes, since its
|
|
Toshihiro Shimizu |
890ddd |
//action interval crosses the junction point
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_splitPars[0] = s->getParameterAtLength(endLen);
|
|
Toshihiro Shimizu |
890ddd |
m_splitPars[1] = s->getParameterAtLength(startLen);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
::splitStroke(*s, m_splitPars, m_splitStrokes);
|
|
Toshihiro Shimizu |
890ddd |
assert(m_splitStrokes.size() >= 3);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_stroke1Idx = 0;
|
|
Toshihiro Shimizu |
890ddd |
m_stroke2Idx = 2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
stroke1 = m_splitStrokes[m_stroke1Idx];
|
|
Toshihiro Shimizu |
890ddd |
stroke2 = m_splitStrokes[m_stroke2Idx];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_actionS2 = m_actionS1 + stroke2->getLength();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TStrokeThicknessDeformation deformer(stroke1, m_actionS1, m_actionRadius);
|
|
Toshihiro Shimizu |
890ddd |
increaseControlPoints(*stroke1, deformer, getPixelSize());
|
|
Toshihiro Shimizu |
890ddd |
TStrokeThicknessDeformation deformer2(stroke2, m_actionS2, m_actionRadius);
|
|
Toshihiro Shimizu |
890ddd |
increaseControlPoints(*stroke2, deformer2, getPixelSize());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
cpCount = stroke2->getControlPointCount();
|
|
Toshihiro Shimizu |
890ddd |
m_cpLenDiff2.resize(cpCount);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < cpCount; ++i)
|
|
Toshihiro Shimizu |
890ddd |
m_cpLenDiff2[i] = stroke2->getLengthAtControlPoint(i) - m_actionS2;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
cpCount = stroke1->getControlPointCount();
|
|
Toshihiro Shimizu |
890ddd |
m_cpLenDiff1.resize(cpCount);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double diff;
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < cpCount; i++) {
|
|
Toshihiro Shimizu |
890ddd |
diff = stroke1->getLengthAtControlPoint(i) - m_actionS1;
|
|
Toshihiro Shimizu |
890ddd |
m_cpLenDiff1[i] = (s->isSelfLoop() && stroke2 && totalLength - diff < diff)
|
|
Toshihiro Shimizu |
890ddd |
? totalLength - diff
|
|
Toshihiro Shimizu |
890ddd |
: diff;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
A split stroke must be reassembled before it is output.
|
|
Toshihiro Shimizu |
890ddd |
In particular, it must be ensured that the merge does not add additional CPS
|
|
Toshihiro Shimizu |
890ddd |
at split points, leaving the output seamless.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
TStroke *PumpTool::mergeStrokes(const std::vector<tstroke *=""> &strokes)</tstroke>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(strokes.size() > 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TStroke *mergedStroke;
|
|
Toshihiro Shimizu |
890ddd |
if (strokes.size() > 1) {
|
|
Toshihiro Shimizu |
890ddd |
if (m_errorTol > 0.0) {
|
|
Toshihiro Shimizu |
890ddd |
strokes[m_stroke1Idx]->reduceControlPoints(m_errorTol);
|
|
Toshihiro Shimizu |
890ddd |
if (m_stroke2Idx >= 0)
|
|
Toshihiro Shimizu |
890ddd |
strokes[m_stroke2Idx]->reduceControlPoints(m_errorTol);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Merge split strokes
|
|
Toshihiro Shimizu |
890ddd |
mergedStroke = merge(strokes);
|
|
Toshihiro Shimizu |
890ddd |
//mergedStroke->reduceControlPoints(0.4*getPixelSize()); //Originally on the whole result...
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_inStroke->isSelfLoop()) {
|
|
Toshihiro Shimizu |
890ddd |
int cpCount = mergedStroke->getControlPointCount();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint p1 = mergedStroke->getControlPoint(0);
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint p2 = mergedStroke->getControlPoint(cpCount - 1);
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint midP = 0.5 * (p1 + p2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
mergedStroke->setControlPoint(0, midP);
|
|
Toshihiro Shimizu |
890ddd |
mergedStroke->setControlPoint(cpCount - 1, midP);
|
|
Toshihiro Shimizu |
890ddd |
mergedStroke->setSelfLoop(true);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
mergedStroke->outlineOptions() = strokes[0]->outlineOptions();
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
mergedStroke = new TStroke(*strokes[0]);
|
|
Toshihiro Shimizu |
890ddd |
if (m_errorTol > 0.0)
|
|
Toshihiro Shimizu |
890ddd |
mergedStroke->reduceControlPoints(m_errorTol);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
mergedStroke->setStyle(m_strokeStyleId);
|
|
Toshihiro Shimizu |
890ddd |
mergedStroke->invalidate();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return mergedStroke;
|
|
Toshihiro Shimizu |
890ddd |
}
|