|
pojienie |
0149f4 |
#include "tenv.h"
|
|
pojienie |
0149f4 |
#include "tproperty.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tools/tool.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tools/toolutils.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/txsheethandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tools/toolhandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tframehandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tcolumnhandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/txshlevelhandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tools/strokeselection.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tmathutil.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstroke.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tools/cursors.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tundo.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tvectorimage.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tthreadmessage.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "toonzqt/imageutils.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonzqt/tselectionhandle.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tgl.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
using namespace ToolUtils;
|
|
Toshihiro Shimizu |
890ddd |
|
|
pojienie |
0149f4 |
TEnv::IntVar SnapAtIntersection("CutterToolSnapAtIntersection", 0);
|
|
pojienie |
0149f4 |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
// UndoCutter
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
d1f6c4 |
class UndoCutter final : public ToolUtils::TToolUndo {
|
|
Shinya Kitaoka |
120a6e |
int m_newStrokeId1;
|
|
Shinya Kitaoka |
120a6e |
int m_newStrokeId2;
|
|
Shinya Kitaoka |
120a6e |
int m_pos;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
VIStroke *m_oldStroke;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::vector<tfilledregioninf> *m_fillInformation;</tfilledregioninf>
|
|
Shinya Kitaoka |
120a6e |
std::vector<doublepair> *m_sortedWRanges;</doublepair>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int m_row;
|
|
Shinya Kitaoka |
120a6e |
int m_column;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
UndoCutter(TXshSimpleLevel *level, const TFrameId &frameId,
|
|
Shinya Kitaoka |
120a6e |
VIStroke *oldStroke, int pos, int newStrokeId1, int newStrokeId2,
|
|
Shinya Kitaoka |
120a6e |
std::vector<tfilledregioninf> *fillInformation,</tfilledregioninf>
|
|
Shinya Kitaoka |
120a6e |
std::vector<doublepair> *sortedWRanges)</doublepair>
|
|
Shinya Kitaoka |
120a6e |
: TToolUndo(level, frameId)
|
|
Shinya Kitaoka |
120a6e |
, m_oldStroke(oldStroke)
|
|
Shinya Kitaoka |
120a6e |
, m_newStrokeId1(newStrokeId1)
|
|
Shinya Kitaoka |
120a6e |
, m_newStrokeId2(newStrokeId2)
|
|
Shinya Kitaoka |
120a6e |
, m_pos(pos)
|
|
Shinya Kitaoka |
120a6e |
, m_fillInformation(fillInformation)
|
|
Shinya Kitaoka |
120a6e |
, m_sortedWRanges(sortedWRanges) {
|
|
Shinya Kitaoka |
120a6e |
TTool::Application *app = TTool::getApplication();
|
|
Shinya Kitaoka |
120a6e |
if (app) {
|
|
Shinya Kitaoka |
120a6e |
m_row = app->getCurrentFrame()->getFrame();
|
|
Shinya Kitaoka |
120a6e |
m_column = app->getCurrentColumn()->getColumnIndex();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
~UndoCutter() {
|
|
Shinya Kitaoka |
120a6e |
deleteVIStroke(m_oldStroke);
|
|
Shinya Kitaoka |
120a6e |
delete m_sortedWRanges;
|
|
Shinya Kitaoka |
120a6e |
delete m_fillInformation;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void undo() const override {
|
|
Shinya Kitaoka |
120a6e |
TTool::Application *app = TTool::getApplication();
|
|
Shinya Kitaoka |
120a6e |
if (!app) return;
|
|
Shinya Kitaoka |
120a6e |
if (dynamic_cast<strokeselection *="">(</strokeselection>
|
|
Shinya Kitaoka |
120a6e |
TTool::getApplication()->getCurrentSelection()->getSelection()))
|
|
Shinya Kitaoka |
120a6e |
TTool::getApplication()->getCurrentSelection()->setSelection(0);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (app->getCurrentFrame()->isEditingScene()) {
|
|
Shinya Kitaoka |
120a6e |
app->getCurrentColumn()->setColumnIndex(m_column);
|
|
Shinya Kitaoka |
120a6e |
app->getCurrentFrame()->setFrame(m_row);
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
app->getCurrentFrame()->setFid(m_frameId);
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP image = m_level->getFrame(m_frameId, true);
|
|
Shinya Kitaoka |
120a6e |
assert(!!image);
|
|
Shinya Kitaoka |
120a6e |
if (!image) return;
|
|
Shinya Kitaoka |
120a6e |
QMutexLocker lock(image->getMutex());
|
|
Shinya Kitaoka |
120a6e |
VIStroke *stroke;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
stroke = image->getStrokeById(m_newStrokeId1);
|
|
Shinya Kitaoka |
120a6e |
if (stroke) image->deleteStroke(stroke);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
stroke = image->getStrokeById(m_newStrokeId2);
|
|
Shinya Kitaoka |
120a6e |
if (stroke) image->deleteStroke(stroke);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
stroke = cloneVIStroke(m_oldStroke);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
image->insertStrokeAt(stroke, m_pos);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
UINT size = m_fillInformation->size();
|
|
Shinya Kitaoka |
120a6e |
if (!size) {
|
|
Shinya Kitaoka |
120a6e |
app->getCurrentXsheet()->notifyXsheetChanged();
|
|
Shinya Kitaoka |
120a6e |
notifyImageChanged();
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
image->findRegions();
|
|
Shinya Kitaoka |
120a6e |
TRegion *reg;
|
|
Shinya Kitaoka |
120a6e |
for (UINT i = 0; i < size; i++) {
|
|
Shinya Kitaoka |
120a6e |
reg = image->getRegion((*m_fillInformation)[i].m_regionId);
|
|
Shinya Kitaoka |
120a6e |
assert(reg);
|
|
Shinya Kitaoka |
120a6e |
if (reg) reg->setStyle((*m_fillInformation)[i].m_styleId);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
app->getCurrentXsheet()->notifyXsheetChanged();
|
|
Shinya Kitaoka |
120a6e |
notifyImageChanged();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void redo() const override {
|
|
Shinya Kitaoka |
120a6e |
TTool::Application *app = TTool::getApplication();
|
|
Shinya Kitaoka |
120a6e |
if (!app) return;
|
|
Shinya Kitaoka |
120a6e |
if (app->getCurrentFrame()->isEditingScene()) {
|
|
Shinya Kitaoka |
120a6e |
app->getCurrentColumn()->setColumnIndex(m_column);
|
|
Shinya Kitaoka |
120a6e |
app->getCurrentFrame()->setFrame(m_row);
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
app->getCurrentFrame()->setFid(m_frameId);
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP image = m_level->getFrame(m_frameId, true);
|
|
Shinya Kitaoka |
120a6e |
assert(!!image);
|
|
Shinya Kitaoka |
120a6e |
if (!image) return;
|
|
Shinya Kitaoka |
120a6e |
QMutexLocker lock(image->getMutex());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool isSelfLoop = image->getStroke(m_pos)->isSelfLoop();
|
|
Shinya Kitaoka |
120a6e |
image->splitStroke(m_pos, *m_sortedWRanges);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
image->getStroke(m_pos)->setId(m_newStrokeId1);
|
|
Shinya Kitaoka |
120a6e |
if (!isSelfLoop && m_sortedWRanges->size() == 2)
|
|
Shinya Kitaoka |
120a6e |
image->getStroke(m_pos + 1)->setId(m_newStrokeId2);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
app->getCurrentXsheet()->notifyXsheetChanged();
|
|
Shinya Kitaoka |
120a6e |
notifyImageChanged();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
int getSize() const override {
|
|
Shinya Kitaoka |
120a6e |
return sizeof(*this) +
|
|
Shinya Kitaoka |
120a6e |
m_fillInformation->capacity() * sizeof(TFilledRegionInf) + 500;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
QString getToolName() override { return QString("Cutter Tool"); }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
// CutterTool
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
d1f6c4 |
class CutterTool final : public TTool {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
bool m_mouseDown;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPointD m_vTan;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TThickPoint m_cursor;
|
|
Shinya Kitaoka |
120a6e |
TPointD m_speed;
|
|
Shinya Kitaoka |
120a6e |
int m_cursorId;
|
|
Shinya Kitaoka |
120a6e |
double m_pW;
|
|
Toshihiro Shimizu |
890ddd |
|
|
pojienie |
86e7f3 |
int m_lockedStrokeIndex;
|
|
pojienie |
86e7f3 |
|
|
pojienie |
0149f4 |
TPropertyGroup m_prop;
|
|
pojienie |
0149f4 |
TBoolProperty m_snapAtIntersection;
|
|
pojienie |
0149f4 |
|
|
Shinya Kitaoka |
120a6e |
CutterTool()
|
|
Shinya Kitaoka |
120a6e |
: TTool("T_Cutter")
|
|
Shinya Kitaoka |
120a6e |
, m_mouseDown(false)
|
|
pojienie |
0149f4 |
, m_cursorId(ToolCursor::CutterCursor)
|
|
pojienie |
0149f4 |
, m_snapAtIntersection("Snap At Intersection", false) {
|
|
Shinya Kitaoka |
120a6e |
bind(TTool::VectorImage);
|
|
pojienie |
0149f4 |
m_prop.bind(m_snapAtIntersection);
|
|
pojienie |
0149f4 |
m_snapAtIntersection.setId("Snap");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
ToolType getToolType() const override { return TTool::LevelWriteTool; }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void draw() override {
|
|
Shinya Kitaoka |
120a6e |
// TAffine viewMatrix = getViewer()->getViewMatrix();
|
|
Shinya Kitaoka |
120a6e |
// glPushMatrix();
|
|
Shinya Kitaoka |
120a6e |
// tglMultMatrix(viewMatrix);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const double pixelSize = getPixelSize();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double len = m_cursor.thick + 15 * pixelSize;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_speed != TPointD(0, 0)) {
|
|
Shinya Kitaoka |
120a6e |
TPointD v = m_speed;
|
|
Shinya Kitaoka |
120a6e |
TPointD p = (TPointD)m_cursor;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
v = rotate90(v);
|
|
Shinya Kitaoka |
120a6e |
v = normalize(v);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
v = v * (len);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
tglColor(TPixelD(0.1, 0.9, 0.1));
|
|
Shinya Kitaoka |
120a6e |
tglDrawSegment(p - v, p + v);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
// glPopMatrix();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
pojienie |
75ef2c |
double getNearestSnapAtIntersection(TStroke *selfStroke, double w) {
|
|
pojienie |
75ef2c |
TVectorImageP vi = TImageP(getImage(false));
|
|
pojienie |
75ef2c |
if (!vi) {
|
|
pojienie |
75ef2c |
return w;
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
|
|
pojienie |
75ef2c |
std::vector<doublepair> intersections;</doublepair>
|
|
pojienie |
75ef2c |
int i, strokeNumber = vi->getStrokeCount();
|
|
pojienie |
75ef2c |
double diff;
|
|
pojienie |
75ef2c |
double nearestW = 1000;
|
|
pojienie |
75ef2c |
double minDiff = 1000;
|
|
pojienie |
75ef2c |
|
|
pojienie |
75ef2c |
// check self intersection first
|
|
pojienie |
75ef2c |
intersect(selfStroke, selfStroke, intersections, false);
|
|
pojienie |
75ef2c |
for (auto &intersection : intersections) {
|
|
pojienie |
75ef2c |
if (areAlmostEqual(intersection.first, 0, 1e-6)) {
|
|
pojienie |
75ef2c |
continue;
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
if (areAlmostEqual(intersection.second, 1, 1e-6)) {
|
|
pojienie |
75ef2c |
continue;
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
|
|
Rozhuk Ivan |
823a31 |
diff = std::abs(intersection.first - w);
|
|
pojienie |
75ef2c |
if (diff < minDiff) {
|
|
pojienie |
75ef2c |
minDiff = diff;
|
|
pojienie |
75ef2c |
nearestW = intersection.first;
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
|
|
Rozhuk Ivan |
823a31 |
diff = std::abs(intersection.second - w);
|
|
pojienie |
75ef2c |
if (diff < minDiff) {
|
|
pojienie |
75ef2c |
minDiff = diff;
|
|
pojienie |
75ef2c |
nearestW = intersection.second;
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
|
|
pojienie |
75ef2c |
if (selfStroke->isSelfLoop()) {
|
|
Rozhuk Ivan |
823a31 |
diff = std::abs(1 - intersection.first) + w;
|
|
pojienie |
75ef2c |
if (diff < minDiff) {
|
|
pojienie |
75ef2c |
minDiff = diff;
|
|
pojienie |
75ef2c |
nearestW = intersection.first;
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
|
|
Rozhuk Ivan |
823a31 |
diff = intersection.first + std::abs(1 - w);
|
|
pojienie |
75ef2c |
if (diff < minDiff) {
|
|
pojienie |
75ef2c |
minDiff = diff;
|
|
pojienie |
75ef2c |
nearestW = intersection.first;
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
|
|
Rozhuk Ivan |
823a31 |
diff = std::abs(1 - intersection.second) + w;
|
|
pojienie |
75ef2c |
if (diff < minDiff) {
|
|
pojienie |
75ef2c |
minDiff = diff;
|
|
pojienie |
75ef2c |
nearestW = intersection.second;
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
|
|
Rozhuk Ivan |
823a31 |
diff = intersection.second + std::abs(1 - w);
|
|
pojienie |
75ef2c |
if (diff < minDiff) {
|
|
pojienie |
75ef2c |
minDiff = diff;
|
|
pojienie |
75ef2c |
nearestW = intersection.second;
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
|
|
pojienie |
75ef2c |
for (i = 0; i < strokeNumber; ++i) {
|
|
pojienie |
75ef2c |
TStroke *stroke = vi->getStroke(i);
|
|
pojienie |
75ef2c |
if (stroke == selfStroke) {
|
|
pojienie |
75ef2c |
continue;
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
|
|
pojienie |
75ef2c |
intersect(selfStroke, stroke, intersections, false);
|
|
pojienie |
75ef2c |
for (auto &intersection : intersections) {
|
|
Rozhuk Ivan |
823a31 |
diff = std::abs(intersection.first - w);
|
|
pojienie |
75ef2c |
if (diff < minDiff) {
|
|
pojienie |
75ef2c |
minDiff = diff;
|
|
pojienie |
75ef2c |
nearestW = intersection.first;
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
|
|
pojienie |
75ef2c |
if (selfStroke->isSelfLoop()) {
|
|
Rozhuk Ivan |
823a31 |
diff = std::abs(1 - intersection.first) + w;
|
|
pojienie |
75ef2c |
if (diff < minDiff) {
|
|
pojienie |
75ef2c |
minDiff = diff;
|
|
pojienie |
75ef2c |
nearestW = intersection.first;
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
|
|
Rozhuk Ivan |
823a31 |
diff = intersection.first + std::abs(1 - w);
|
|
pojienie |
75ef2c |
if (diff < minDiff) {
|
|
pojienie |
75ef2c |
minDiff = diff;
|
|
pojienie |
75ef2c |
nearestW = intersection.first;
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
|
|
pojienie |
75ef2c |
if (nearestW >= 0 && nearestW <= 1) {
|
|
pojienie |
75ef2c |
return nearestW;
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
return w;
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
|
|
pojienie |
86e7f3 |
void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override {
|
|
manongjohn |
40a40e |
if (getViewer() && getViewer()->getGuidedStrokePickerMode()) {
|
|
manongjohn |
40a40e |
getViewer()->doPickGuideStroke(pos);
|
|
manongjohn |
40a40e |
return;
|
|
manongjohn |
40a40e |
}
|
|
manongjohn |
40a40e |
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP vi = TImageP(getImage(true));
|
|
Shinya Kitaoka |
120a6e |
if (!vi) return;
|
|
Shinya Kitaoka |
120a6e |
QMutexLocker sl(vi->getMutex());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double dist, pW;
|
|
Shinya Kitaoka |
120a6e |
UINT strokeIndex;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TStroke *strokeRef;
|
|
Shinya Kitaoka |
120a6e |
|
|
pojienie |
86e7f3 |
if (getNearestStrokeWithLock(pos, pW, strokeIndex, dist,
|
|
pojienie |
86e7f3 |
e.isCtrlPressed()) &&
|
|
pojienie |
86e7f3 |
pW >= 0 && pW <= 1) {
|
|
Shinya Kitaoka |
120a6e |
double w;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
strokeRef = vi->getStroke(strokeIndex);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double hitPointLen = strokeRef->getLength(pW);
|
|
Shinya Kitaoka |
120a6e |
double totalLen = strokeRef->getLength();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double len = hitPointLen;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!strokeRef->isSelfLoop()) {
|
|
Shinya Kitaoka |
120a6e |
if (len < TConsts::epsilon)
|
|
Shinya Kitaoka |
120a6e |
w = 0;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
w = strokeRef->getParameterAtLength(len);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (len > totalLen - TConsts::epsilon)
|
|
Shinya Kitaoka |
120a6e |
w = 1;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
w = strokeRef->getParameterAtLength(len);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (len < 0) len += totalLen;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (len > totalLen) len -= totalLen;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
w = strokeRef->getParameterAtLength(len);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
pojienie |
75ef2c |
if (m_snapAtIntersection.getValue()) {
|
|
pojienie |
75ef2c |
w = getNearestSnapAtIntersection(strokeRef, w);
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
|
|
Shinya Kitaoka |
120a6e |
std::vector<doublepair> *sortedWRanges = new std::vector<doublepair>;</doublepair></doublepair>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (strokeRef->isSelfLoop()) {
|
|
Shinya Kitaoka |
120a6e |
sortedWRanges->push_back(std::make_pair(0, w));
|
|
Shinya Kitaoka |
120a6e |
sortedWRanges->push_back(std::make_pair(w, 1));
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (w == 0 || w == 1)
|
|
Shinya Kitaoka |
120a6e |
sortedWRanges->push_back(std::make_pair(0, 1));
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
sortedWRanges->push_back(std::make_pair(0, w));
|
|
Shinya Kitaoka |
120a6e |
sortedWRanges->push_back(std::make_pair(w, 1));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::vector<tfilledregioninf> *fillInformation =</tfilledregioninf>
|
|
Shinya Kitaoka |
120a6e |
new std::vector<tfilledregioninf>;</tfilledregioninf>
|
|
Shinya Kitaoka |
120a6e |
ImageUtils::getFillingInformationOverlappingArea(vi, *fillInformation,
|
|
Shinya Kitaoka |
120a6e |
strokeRef->getBBox());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
VIStroke *oldStroke = cloneVIStroke(vi->getVIStroke(strokeIndex));
|
|
Shinya Kitaoka |
120a6e |
bool isSelfLoop = vi->getStroke(strokeIndex)->isSelfLoop();
|
|
Shinya Kitaoka |
120a6e |
vi->splitStroke(strokeIndex, *sortedWRanges);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TUndo *nundo;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TXshSimpleLevel *sl =
|
|
Shinya Kitaoka |
120a6e |
TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
|
|
Shinya Kitaoka |
120a6e |
assert(sl);
|
|
Shinya Kitaoka |
120a6e |
TFrameId id = getCurrentFid();
|
|
Shinya Kitaoka |
120a6e |
if (isSelfLoop || sortedWRanges->size() == 1) {
|
|
Shinya Kitaoka |
120a6e |
nundo = new UndoCutter(sl, id, oldStroke, strokeIndex,
|
|
Shinya Kitaoka |
120a6e |
vi->getStroke(strokeIndex)->getId(), -1,
|
|
Shinya Kitaoka |
120a6e |
fillInformation, sortedWRanges);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
assert(strokeIndex + 1 < vi->getStrokeCount());
|
|
Shinya Kitaoka |
120a6e |
nundo = new UndoCutter(sl, id, oldStroke, strokeIndex,
|
|
Shinya Kitaoka |
120a6e |
vi->getStroke(strokeIndex)->getId(),
|
|
Shinya Kitaoka |
120a6e |
vi->getStroke(strokeIndex + 1)->getId(),
|
|
Shinya Kitaoka |
120a6e |
fillInformation, sortedWRanges);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->add(nundo);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
invalidate();
|
|
Shinya Kitaoka |
120a6e |
notifyImageChanged();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
invalidate();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void mouseMove(const TPointD &pos, const TMouseEvent &e) override {
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP vi = TImageP(getImage(true));
|
|
Shinya Kitaoka |
120a6e |
if (!vi) {
|
|
Shinya Kitaoka |
120a6e |
m_speed = TPointD(0, 0);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// select nearest stroke and finds its parameter
|
|
Shinya Kitaoka |
120a6e |
double dist, pW;
|
|
Shinya Kitaoka |
120a6e |
UINT stroke;
|
|
Shinya Kitaoka |
120a6e |
|
|
pojienie |
86e7f3 |
if (getNearestStrokeWithLock(pos, pW, stroke, dist, e.isCtrlPressed())) {
|
|
Shinya Kitaoka |
120a6e |
TStroke *strokeRef = vi->getStroke(stroke);
|
|
pojienie |
75ef2c |
|
|
pojienie |
75ef2c |
if (m_snapAtIntersection.getValue()) {
|
|
pojienie |
75ef2c |
pW = getNearestSnapAtIntersection(strokeRef, pW);
|
|
pojienie |
75ef2c |
}
|
|
pojienie |
75ef2c |
|
|
pojienie |
75ef2c |
m_speed = strokeRef->getSpeed(pW);
|
|
pojienie |
75ef2c |
m_cursor = strokeRef->getThickPoint(pW);
|
|
pojienie |
75ef2c |
m_pW = pW;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
m_speed = TPointD(0, 0);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
invalidate();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void onLeave() override { m_speed = TPointD(0, 0); }
|
|
Shinya Kitaoka |
120a6e |
|
|
pojienie |
0149f4 |
void onActivate() override {
|
|
pojienie |
0149f4 |
m_snapAtIntersection.setValue(SnapAtIntersection ? 1 : 0);
|
|
pojienie |
0149f4 |
}
|
|
Shinya Kitaoka |
473e70 |
void onEnter() override {
|
|
Shinya Kitaoka |
120a6e |
if ((TVectorImageP)getImage(false))
|
|
Shinya Kitaoka |
120a6e |
m_cursorId = ToolCursor::CutterCursor;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
m_cursorId = ToolCursor::CURSOR_NO;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
manongjohn |
40a40e |
int getCursorId() const override {
|
|
manongjohn |
40a40e |
if (m_viewer && m_viewer->getGuidedStrokePickerMode())
|
|
manongjohn |
40a40e |
return m_viewer->getGuidedStrokePickerCursor();
|
|
manongjohn |
40a40e |
return m_cursorId;
|
|
manongjohn |
40a40e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
pojienie |
0149f4 |
void updateTranslation() override {
|
|
pojienie |
0149f4 |
m_snapAtIntersection.setQStringName(QObject::tr("Snap At Intersection"));
|
|
pojienie |
0149f4 |
}
|
|
pojienie |
0149f4 |
|
|
pojienie |
0149f4 |
TPropertyGroup *getProperties(int targetType) override { return &m_prop; }
|
|
pojienie |
0149f4 |
|
|
pojienie |
0149f4 |
bool onPropertyChanged(std::string propertyName) override {
|
|
pojienie |
0149f4 |
SnapAtIntersection = (int)(m_snapAtIntersection.getValue());
|
|
pojienie |
0149f4 |
return true;
|
|
pojienie |
0149f4 |
}
|
|
pojienie |
0149f4 |
|
|
pojienie |
86e7f3 |
bool getNearestStrokeWithLock(const TPointD &p, double &outW,
|
|
pojienie |
86e7f3 |
UINT &strokeIndex, double &dist2, bool lock) {
|
|
pojienie |
86e7f3 |
TVectorImageP vi = TImageP(getImage(false));
|
|
pojienie |
86e7f3 |
if (!vi) return false;
|
|
pojienie |
86e7f3 |
|
|
pojienie |
86e7f3 |
if (m_lockedStrokeIndex >= vi->getStrokeCount()) {
|
|
pojienie |
86e7f3 |
m_lockedStrokeIndex = -1;
|
|
pojienie |
86e7f3 |
}
|
|
pojienie |
86e7f3 |
|
|
pojienie |
86e7f3 |
if (lock && m_lockedStrokeIndex >= 0) {
|
|
pojienie |
86e7f3 |
TStroke *stroke = vi->getStroke(m_lockedStrokeIndex);
|
|
pojienie |
86e7f3 |
strokeIndex = m_lockedStrokeIndex;
|
|
pojienie |
86e7f3 |
return stroke->getNearestW(p, outW, dist2);
|
|
pojienie |
86e7f3 |
}
|
|
pojienie |
86e7f3 |
|
|
pojienie |
86e7f3 |
UINT index;
|
|
pojienie |
86e7f3 |
if (vi->getNearestStroke(p, outW, index, dist2)) {
|
|
pojienie |
86e7f3 |
m_lockedStrokeIndex = index;
|
|
pojienie |
86e7f3 |
strokeIndex = index;
|
|
pojienie |
86e7f3 |
return true;
|
|
pojienie |
86e7f3 |
}
|
|
pojienie |
86e7f3 |
|
|
pojienie |
86e7f3 |
return false;
|
|
pojienie |
86e7f3 |
}
|
|
pojienie |
86e7f3 |
|
|
Toshihiro Shimizu |
890ddd |
} cutterTool;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// TTool *getCutterTool() {return &cutterTool;}
|