| |
| |
| #include "tundo.h" |
| #include "tthreadmessage.h" |
| #include "tvectorimage.h" |
| #include "drawutil.h" |
| #include "controlpointselection.h" |
| #include "tproperty.h" |
| #include "tenv.h" |
| |
| #include "tools/tool.h" |
| #include "tools/toolutils.h" |
| #include "tools/cursors.h" |
| #include "tools/toolhandle.h" |
| |
| #include "toonz/tframehandle.h" |
| #include "toonz/tcolumnhandle.h" |
| #include "toonz/txsheethandle.h" |
| #include "toonz/txshlevelhandle.h" |
| #include "toonz/tobjecthandle.h" |
| #include "toonz/stage2.h" |
| #include "toonz/tstageobject.h" |
| |
| #include "tw/keycodes.h" |
| |
| |
| #include <QCoreApplication> |
| |
| using namespace ToolUtils; |
| |
| TEnv::IntVar AutoSelectDrawing("ControlPointEditorToolAutoSelectDrawing", 1); |
| |
| |
| namespace |
| { |
| |
| |
| |
| |
| |
| void getSegmentParameter(ControlPointEditorStroke *cpEditor, int beforeIndex, int nextIndex, |
| double &w0, double &w1, double &q0, double &q1) |
| { |
| TStroke *stroke = cpEditor->getStroke(); |
| if (!stroke) |
| return; |
| q0 = q1 = w0 = w1 = -1; |
| int cpCount = cpEditor->getControlPointCount(); |
| |
| if (cpEditor->isSpeedOutLinear(beforeIndex) || cpEditor->isSpeedInLinear(beforeIndex) || cpEditor->isCusp(beforeIndex)) { |
| if (cpEditor->isSelfLoop() && beforeIndex == 0 && nextIndex == cpCount - 1) |
| w1 = 1; |
| else |
| w0 = stroke->getParameterAtControlPoint(cpEditor->getIndexPointInStroke(beforeIndex)); |
| } else |
| { |
| if (!cpEditor->isSelfLoop() || beforeIndex != 0) |
| w0 = stroke->getParameterAtControlPoint(cpEditor->getIndexPointInStroke(beforeIndex) - 4); |
| else { |
| if (nextIndex == 1) |
| { |
| w0 = 0; |
| q0 = stroke->getParameterAtControlPoint(cpEditor->getIndexPointInStroke(cpCount - 1)); |
| q1 = 1; |
| } else if (nextIndex == cpCount - 1) |
| { |
| w1 = 1; |
| q0 = 0; |
| q1 = stroke->getParameterAtControlPoint(cpEditor->getIndexPointInStroke(1)); |
| } else { |
| assert(0); |
| } |
| } |
| } |
| |
| if (cpEditor->isSpeedInLinear(nextIndex) || cpEditor->isSpeedOutLinear(nextIndex) || cpEditor->isCusp(nextIndex)) { |
| if (cpEditor->isSelfLoop() && beforeIndex == 0 && nextIndex == cpCount - 1) |
| w0 = stroke->getParameterAtControlPoint(cpEditor->getIndexPointInStroke(nextIndex)); |
| else |
| w1 = stroke->getParameterAtControlPoint(cpEditor->getIndexPointInStroke(nextIndex)); |
| } else |
| { |
| if (!cpEditor->isSelfLoop() || nextIndex != cpCount - 1 || beforeIndex != 0) |
| w1 = stroke->getParameterAtControlPoint(cpEditor->getIndexPointInStroke(nextIndex) + 4); |
| else if (nextIndex == cpCount - 1) |
| w0 = stroke->getParameterAtControlPoint(cpEditor->getIndexPointInStroke(nextIndex) - 4); |
| else { |
| assert(0); |
| } |
| } |
| } |
| |
| } |
| |
| |
| |
| |
| class ControlPointEditorTool : public TTool |
| { |
| Q_DECLARE_TR_FUNCTIONS(ControlPointEditorTool) |
| |
| bool m_draw; |
| bool m_isMenuViewed; |
| int m_lastPointSelected; |
| bool m_isImageChanged; |
| ControlPointSelection m_selection; |
| ControlPointEditorStroke m_controlPointEditorStroke; |
| std::pair<int, int> m_moveSegmentLimitation; |
| ControlPointEditorStroke m_moveControlPointEditorStroke; |
| TRectD m_selectingRect; |
| TPointD m_pos; |
| |
| TPropertyGroup m_prop; |
| TBoolProperty m_autoSelectDrawing; |
| |
| enum Action { NONE, |
| RECT_SELECTION, |
| CP_MOVEMENT, |
| SEGMENT_MOVEMENT, |
| IN_SPEED_MOVEMENT, |
| OUT_SPEED_MOVEMENT }; |
| Action m_action; |
| |
| enum CursorType { NORMAL, |
| ADD, |
| EDIT_SPEED, |
| EDIT_SEGMENT, |
| NO_ACTIVE }; |
| CursorType m_cursorType; |
| |
| TUndo *m_undo; |
| |
| public: |
| ControlPointEditorTool(); |
| |
| ToolType getToolType() const { return TTool::LevelWriteTool; } |
| |
| void updateTranslation(); |
| |
| TPropertyGroup *getProperties(int targetType) { return &m_prop; } |
| |
| |
| void onSelectionChanged() { invalidate(); } |
| |
| |
| |
| bool select(const TSelection *) { return false; } |
| ControlPointEditorStroke getControlPointEditorStroke() { return m_controlPointEditorStroke; }; |
| |
| void initUndo(); |
| |
| void getNearestStrokeColumnIndexes(std::vector<int> &indexes, TPointD pos); |
| |
| void drawMovingSegment(); |
| void drawControlPoint(); |
| void draw(); |
| void mouseMove(const TPointD &pos, const TMouseEvent &e); |
| void leftButtonDown(const TPointD &pos, const TMouseEvent &e); |
| void rightButtonDown(const TPointD &pos, const TMouseEvent &); |
| |
| void moveControlPoints(const TPointD &delta); |
| void moveSpeed(const TPointD &delta, bool isIn); |
| void moveSegment(const TPointD &delta, bool dragging, bool isShiftPressed); |
| |
| void leftButtonDrag(const TPointD &pos, const TMouseEvent &e); |
| void leftButtonUp(const TPointD &pos, const TMouseEvent &e); |
| void addContextMenuItems(QMenu *menu); |
| |
| void linkSpeedInOut(int index); |
| void unlinkSpeedInOut(int pointIndex); |
| |
| bool keyDown(int key, TUINT32 flags, const TPoint &pos); |
| void onEnter(); |
| void onLeave(); |
| bool onPropertyChanged(std::string propertyName); |
| |
| void onActivate(); |
| void onDeactivate(); |
| void onImageChanged(); |
| int getCursorId() const; |
| |
| } controlPointEditorTool; |
| |
| |
| |
| |
| |
| ControlPointEditorTool::ControlPointEditorTool() |
| : TTool("T_ControlPointEditor"), m_draw(false), m_lastPointSelected(-1), m_isImageChanged(false), m_selectingRect(TRectD()), m_autoSelectDrawing("Auto Select Drawing", true), m_action(NONE), m_cursorType(NORMAL), m_undo(0), m_isMenuViewed(false), m_moveControlPointEditorStroke(), m_moveSegmentLimitation() |
| { |
| bind(TTool::Vectors); |
| m_prop.bind(m_autoSelectDrawing); |
| m_selection.setControlPointEditorStroke(&m_controlPointEditorStroke); |
| |
| m_autoSelectDrawing.setId("AutoSelectDrawing"); |
| } |
| |
| |
| |
| void ControlPointEditorTool::updateTranslation() |
| { |
| m_autoSelectDrawing.setQStringName(tr("Auto Select Drawing")); |
| } |
| |
| |
| |
| void ControlPointEditorTool::initUndo() |
| { |
| if (TTool::getApplication()->getCurrentObject()->isSpline()) { |
| m_undo = new UndoPath(getXsheet()->getStageObject(getObjectId())->getSpline()); |
| return; |
| } |
| TVectorImageP vi(getImage(false)); |
| if (!vi) |
| return; |
| TXshSimpleLevel *level = TTool::getApplication()->getCurrentLevel()->getSimpleLevel(); |
| UndoControlPointEditor *undo = new UndoControlPointEditor(level, getCurrentFid()); |
| int index = m_controlPointEditorStroke.getStrokeIndex(); |
| if (index > -1) |
| undo->addOldStroke(index, vi->getVIStroke(index)); |
| m_undo = undo; |
| } |
| |
| |
| |
| void ControlPointEditorTool::getNearestStrokeColumnIndexes(std::vector<int> &indexes, TPointD pos) |
| { |
| TTool::Application *app = TTool::getApplication(); |
| TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); |
| int currentFrame = app->getCurrentFrame()->getFrameIndex(); |
| std::vector<int> newIndexes; |
| TAffine aff = getMatrix(); |
| int i = 0; |
| for (i = 0; i < (int)indexes.size(); i++) { |
| if (xsh->getColumn(i)->isLocked()) |
| continue; |
| int index = indexes[i]; |
| TVectorImageP vi = xsh->getCell(currentFrame, index).getImage(false); |
| if (!vi) |
| continue; |
| double dist2, t = 0; |
| UINT strokeIndex = -1; |
| TPointD p = getColumnMatrix(index).inv() * getMatrix() * pos; |
| if (vi->getNearestStroke(p, t, strokeIndex, dist2) && dist2 < 25 * getPixelSize() * getPixelSize()) |
| newIndexes.push_back(index); |
| } |
| indexes.clear(); |
| indexes = newIndexes; |
| } |
| |
| |
| |
| void ControlPointEditorTool::drawMovingSegment() |
| { |
| int beforeIndex = m_moveSegmentLimitation.first; |
| int nextIndex = m_moveSegmentLimitation.second; |
| if (m_action != EDIT_SEGMENT || beforeIndex == -1 || nextIndex == -1 || !m_moveControlPointEditorStroke.getStroke()) |
| return; |
| tglColor(TPixel::Green); |
| double w0, w1; |
| double q0, q1; |
| getSegmentParameter(&m_moveControlPointEditorStroke, beforeIndex, nextIndex, w0, w1, q0, q1); |
| if (w0 != -1 && w1 != -1) |
| drawStrokeCenterline(*m_moveControlPointEditorStroke.getStroke(), getPixelSize(), w0, w1); |
| if (q0 != -1 && q1 != -1) |
| drawStrokeCenterline(*m_moveControlPointEditorStroke.getStroke(), getPixelSize(), q0, q1); |
| } |
| |
| |
| |
| void ControlPointEditorTool::drawControlPoint() |
| { |
| TPixel color1 = TPixel(79, 128, 255); |
| TPixel color2 = TPixel::White; |
| TPixel color_handle = TPixel(96, 64, 201); |
| int controlPointCount = m_controlPointEditorStroke.getControlPointCount(); |
| |
| double pix = getPixelSize() * 2.0f; |
| double pix1_5 = 1.5 * pix, pix2 = pix + pix, pix2_5 = pix1_5 + pix, |
| pix3 = pix2 + pix, pix3_5 = pix2_5 + pix, pix4 = pix3 + pix; |
| |
| double maxDist2 = sq(5.0 * pix); |
| double dist2 = 0; |
| int pointIndex; |
| ControlPointEditorStroke::PointType pointType = m_controlPointEditorStroke.getPointTypeAt(m_pos, maxDist2, pointIndex); |
| int i; |
| for (i = 0; i < controlPointCount; i++) { |
| TThickPoint point = m_controlPointEditorStroke.getControlPoint(i); |
| TPointD pa = m_controlPointEditorStroke.getSpeedInPoint(i); |
| TPointD pb = m_controlPointEditorStroke.getSpeedOutPoint(i); |
| tglColor(color_handle); |
| tglDrawSegment(pa, point); |
| if (i == pointIndex && pointType == ControlPointEditorStroke::SPEED_IN) |
| tglFillRect(pa.x - pix2_5, pa.y - pix2_5, pa.x + pix2_5, pa.y + pix2_5); |
| else |
| tglFillRect(pa.x - pix1_5, pa.y - pix1_5, pa.x + pix1_5, pa.y + pix1_5); |
| |
| tglDrawSegment(pb, point); |
| if (i == pointIndex && pointType == ControlPointEditorStroke::SPEED_OUT) |
| tglFillRect(pb.x - pix2_5, pb.y - pix2_5, pb.x + pix2_5, pb.y + pix2_5); |
| else |
| tglFillRect(pb.x - pix1_5, pb.y - pix1_5, pb.x + pix1_5, pb.y + pix1_5); |
| |
| tglColor(color1); |
| |
| if (i == pointIndex && pointType == ControlPointEditorStroke::CONTROL_POINT) { |
| tglFillRect(point.x - pix3_5, point.y - pix3_5, point.x + pix3_5, point.y + pix3_5); |
| if (!m_selection.isSelected(i)) { |
| tglColor(color2); |
| tglFillRect(point.x - pix2_5, point.y - pix2_5, point.x + pix2_5, point.y + pix2_5); |
| } |
| } else { |
| tglFillRect(point.x - pix2, point.y - pix2, point.x + pix2, point.y + pix2); |
| if (!m_selection.isSelected(i)) { |
| tglColor(color2); |
| tglFillRect(point.x - pix, point.y - pix, point.x + pix, point.y + pix); |
| } |
| } |
| } |
| } |
| |
| |
| |
| void ControlPointEditorTool::draw() |
| { |
| TVectorImageP vi(getImage(false)); |
| if (!m_draw) |
| return; |
| |
| int currentStroke = m_controlPointEditorStroke.getStrokeIndex(); |
| if (!vi || currentStroke == -1 || m_controlPointEditorStroke.getControlPointCount() == 0 || |
| vi->getStrokeCount() == 0 || (int)vi->getStrokeCount() <= currentStroke) { |
| m_controlPointEditorStroke.setStroke((TVectorImage *)0, -1); |
| return; |
| } |
| |
| TPixel color1, color2; |
| if (m_action == RECT_SELECTION) |
| { |
| color1 = TPixel32::Black; |
| drawRect(m_selectingRect, color1, 0x3F33, true); |
| } |
| |
| if (m_controlPointEditorStroke.getControlPointCount() <= 0) |
| return; |
| |
| color1 = TPixel(79, 128, 255); |
| color2 = TPixel::White; |
| TStroke *stroke = m_controlPointEditorStroke.getStroke(); |
| tglColor(color1); |
| drawStrokeCenterline(*stroke, getPixelSize()); |
| |
| drawControlPoint(); |
| |
| drawMovingSegment(); |
| } |
| |
| |
| |
| void ControlPointEditorTool::mouseMove(const TPointD &pos, const TMouseEvent &e) |
| { |
| |
| TVectorImageP vi(getImage(false)); |
| if (!vi) { |
| m_controlPointEditorStroke.setStroke((TVectorImage *)0, -1); |
| m_cursorType = NO_ACTIVE; |
| return; |
| } else |
| m_cursorType = NORMAL; |
| |
| m_pos = pos; |
| |
| if (!m_draw || m_controlPointEditorStroke.getStrokeIndex() == -1) |
| return; |
| if (e.isAltPressed()) |
| m_cursorType = EDIT_SPEED; |
| else { |
| double maxDist = 5 * getPixelSize(); |
| double maxDist2 = maxDist * maxDist; |
| int pointIndexCP; |
| ControlPointEditorStroke::PointType pointType = m_controlPointEditorStroke.getPointTypeAt(pos, maxDist2, pointIndexCP); |
| if (pointType == ControlPointEditorStroke::SEGMENT && e.isCtrlPressed()) |
| m_cursorType = ADD; |
| |
| |
| else |
| m_cursorType = NORMAL; |
| } |
| invalidate(); |
| } |
| |
| |
| |
| void ControlPointEditorTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) |
| { |
| m_pos = pos; |
| double maxDist = 5 * getPixelSize(); |
| double maxDist2 = maxDist * maxDist; |
| double dist2 = 0; |
| int pointIndex; |
| ControlPointEditorStroke::PointType pointType = m_controlPointEditorStroke.getPointTypeAt(pos, maxDist2, pointIndex); |
| |
| if (pointType == ControlPointEditorStroke::NONE) { |
| |
| TTool::Application *app = TTool::getApplication(); |
| if (m_autoSelectDrawing.getValue()) { |
| |
| std::vector<int> columnIndexes; |
| getViewer()->posToColumnIndexes(e.m_pos, columnIndexes, getPixelSize() * 5, false); |
| getNearestStrokeColumnIndexes(columnIndexes, pos); |
| if (!columnIndexes.empty()) { |
| int currentColumnIndex = app->getCurrentColumn()->getColumnIndex(); |
| int columnIndex; |
| if (columnIndexes.size() == 1) |
| columnIndex = columnIndexes[0]; |
| else { |
| ToolUtils::ColumChooserMenu *menu = new ToolUtils::ColumChooserMenu(app->getCurrentXsheet()->getXsheet(), columnIndexes); |
| m_isMenuViewed = true; |
| columnIndex = menu->execute(); |
| } |
| TXshColumn *column = app->getCurrentXsheet()->getXsheet()->getColumn(columnIndex); |
| if (columnIndex >= 0 && columnIndex != currentColumnIndex && column && !column->isLocked()) { |
| TAffine aff = getMatrix(); |
| app->getCurrentColumn()->setColumnIndex(columnIndex); |
| updateMatrix(); |
| currentColumnIndex = columnIndex; |
| m_pos = getMatrix().inv() * aff * pos; |
| } |
| } |
| } |
| |
| TVectorImageP vi = getImage(false); |
| if (!vi) |
| return; |
| double dist2, t = 0; |
| UINT index = -1; |
| if (vi->getNearestStroke(m_pos, t, index, dist2) && dist2 < 25 * getPixelSize() * getPixelSize()) { |
| |
| assert(0 <= index && index < vi->getStrokeCount()); |
| m_controlPointEditorStroke.setStroke(vi, index); |
| m_action = NONE; |
| m_selection.makeCurrent(); |
| } else { |
| |
| m_selectingRect = TRectD(m_pos.x, m_pos.y, m_pos.x + 1, m_pos.y + 1); |
| if (m_selectingRect.x0 > m_selectingRect.x1) |
| tswap(m_selectingRect.x1, m_selectingRect.x0); |
| if (m_selectingRect.y0 > m_selectingRect.y1) |
| tswap(m_selectingRect.y1, m_selectingRect.y0); |
| m_action = RECT_SELECTION; |
| } |
| m_selection.selectNone(); |
| return; |
| } |
| TVectorImageP vi = getImage(true); |
| if (!vi) |
| return; |
| |
| if (pointType == ControlPointEditorStroke::SPEED_IN || pointType == ControlPointEditorStroke::SPEED_OUT) { |
| bool isIn = pointType == ControlPointEditorStroke::SPEED_IN; |
| m_selection.selectNone(); |
| m_selection.select(pointIndex); |
| m_action = isIn ? IN_SPEED_MOVEMENT : OUT_SPEED_MOVEMENT; |
| if (e.isAltPressed()) { |
| initUndo(); |
| if (m_controlPointEditorStroke.isCusp(pointIndex)) |
| linkSpeedInOut(pointIndex); |
| else |
| unlinkSpeedInOut(pointIndex); |
| TUndoManager::manager()->add(m_undo); |
| m_undo = 0; |
| } |
| m_selection.makeCurrent(); |
| } else if (pointType == ControlPointEditorStroke::CONTROL_POINT) { |
| if (e.isAltPressed()) { |
| m_selection.selectNone(); |
| m_selection.select(pointIndex); |
| initUndo(); |
| bool isSpeedIn = m_controlPointEditorStroke.isSpeedInLinear(pointIndex); |
| bool isSpeedOut = m_controlPointEditorStroke.isSpeedOutLinear(pointIndex); |
| m_controlPointEditorStroke.setLinear(pointIndex, !isSpeedIn && !isSpeedOut); |
| TUndoManager::manager()->add(m_undo); |
| m_undo = 0; |
| return; |
| } |
| if (e.isCtrlPressed()) { |
| if (m_selection.isSelected(pointIndex)) |
| m_selection.unselect(pointIndex); |
| else |
| m_selection.select(pointIndex); |
| } else if (m_selection.isEmpty() || !m_selection.isSelected(pointIndex)) { |
| m_selection.selectNone(); |
| m_selection.select(pointIndex); |
| } |
| m_lastPointSelected = pointIndex; |
| m_action = CP_MOVEMENT; |
| m_selection.makeCurrent(); |
| } else if (pointType == ControlPointEditorStroke::SEGMENT && !e.isAltPressed()) { |
| m_selection.selectNone(); |
| if (e.isCtrlPressed()) { |
| |
| initUndo(); |
| pointIndex = m_controlPointEditorStroke.addControlPoint(pos); |
| m_selection.select(pointIndex); |
| m_action = CP_MOVEMENT; |
| TUndoManager::manager()->add(m_undo); |
| m_lastPointSelected = -1; |
| notifyImageChanged(); |
| } else { |
| |
| int precPointIndex, nextPointIndex; |
| precPointIndex = pointIndex; |
| nextPointIndex = (m_controlPointEditorStroke.isSelfLoop() && |
| precPointIndex == m_controlPointEditorStroke.getControlPointCount() - 1) |
| ? 0 |
| : precPointIndex + 1; |
| if (precPointIndex > -1 && nextPointIndex > -1) { |
| if (precPointIndex > nextPointIndex) |
| tswap(precPointIndex, nextPointIndex); |
| m_moveSegmentLimitation.first = precPointIndex; |
| m_moveSegmentLimitation.second = nextPointIndex; |
| } |
| m_moveControlPointEditorStroke = *m_controlPointEditorStroke.clone(); |
| |
| if (e.isShiftPressed()) { |
| if (!m_controlPointEditorStroke.isCusp(precPointIndex)) { |
| m_controlPointEditorStroke.setCusp(precPointIndex, true, false); |
| m_moveControlPointEditorStroke.setCusp(precPointIndex, true, false); |
| } |
| if (!m_controlPointEditorStroke.isCusp(nextPointIndex)) { |
| m_controlPointEditorStroke.setCusp(nextPointIndex, true, true); |
| m_moveControlPointEditorStroke.setCusp(nextPointIndex, true, true); |
| } |
| } |
| m_action = SEGMENT_MOVEMENT; |
| } |
| m_selection.makeCurrent(); |
| } |
| |
| int currentStroke = m_controlPointEditorStroke.getStrokeIndex(); |
| if (currentStroke != -1) |
| initUndo(); |
| invalidate(); |
| m_isImageChanged = false; |
| } |
| |
| |
| |
| void ControlPointEditorTool::rightButtonDown(const TPointD &pos, const TMouseEvent &) |
| { |
| TVectorImageP vi = getImage(true); |
| if (!vi) |
| return; |
| double maxDist = 5 * getPixelSize(); |
| double maxDist2 = maxDist * maxDist; |
| double dist2 = 0; |
| int pointIndex; |
| ControlPointEditorStroke::PointType pointType = m_controlPointEditorStroke.getPointTypeAt(pos, maxDist2, pointIndex); |
| if (pointType != ControlPointEditorStroke::CONTROL_POINT) |
| return; |
| m_selection.select(pointIndex); |
| } |
| |
| |
| |
| void ControlPointEditorTool::moveControlPoints(const TPointD &delta) |
| { |
| int i; |
| int cpCount = m_controlPointEditorStroke.getControlPointCount(); |
| for (i = 0; i < cpCount; i++) |
| if (m_selection.isSelected(i)) |
| m_controlPointEditorStroke.moveControlPoint(i, delta); |
| } |
| |
| |
| |
| void ControlPointEditorTool::moveSpeed(const TPointD &delta, bool isIn) |
| { |
| int i; |
| for (i = 0; i < m_controlPointEditorStroke.getControlPointCount(); i++) |
| if (m_selection.isSelected(i)) |
| m_controlPointEditorStroke.moveSpeed(i, delta, isIn, 4 * getPixelSize()); |
| } |
| |
| |
| |
| void ControlPointEditorTool::moveSegment(const TPointD &delta, bool dragging, bool isShiftPressed) |
| { |
| int beforeIndex = m_moveSegmentLimitation.first; |
| int nextIndex = m_moveSegmentLimitation.second; |
| |
| if (isShiftPressed) { |
| if (!m_controlPointEditorStroke.isCusp(beforeIndex)) { |
| if (dragging) |
| m_moveControlPointEditorStroke.setCusp(beforeIndex, true, false); |
| else |
| m_controlPointEditorStroke.setCusp(beforeIndex, true, false); |
| } |
| if (!m_controlPointEditorStroke.isCusp(nextIndex)) { |
| if (dragging) |
| m_moveControlPointEditorStroke.setCusp(nextIndex, true, true); |
| else |
| m_controlPointEditorStroke.setCusp(nextIndex, true, true); |
| } |
| } |
| if (dragging) |
| m_moveControlPointEditorStroke.moveSegment(beforeIndex, nextIndex, delta, m_pos); |
| else |
| m_controlPointEditorStroke.moveSegment(beforeIndex, nextIndex, delta, m_pos); |
| } |
| |
| |
| |
| void ControlPointEditorTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) |
| { |
| TVectorImageP vi(getImage(true)); |
| int currentStroke = m_controlPointEditorStroke.getStrokeIndex(); |
| if (!vi || currentStroke == -1 || m_action == NONE) |
| return; |
| QMutexLocker lock(vi->getMutex()); |
| |
| TPointD delta = pos - m_pos; |
| |
| if (m_action == CP_MOVEMENT) { |
| m_pos = pos; |
| if (!m_selection.isSelected(m_lastPointSelected) && e.isCtrlPressed()) |
| m_selection.select(m_lastPointSelected); |
| moveControlPoints(delta); |
| m_isImageChanged = true; |
| } |
| if (m_action == SEGMENT_MOVEMENT) { |
| m_moveControlPointEditorStroke = *m_controlPointEditorStroke.clone(); |
| moveSegment(delta, true, e.isShiftPressed()); |
| m_isImageChanged = true; |
| } |
| if (m_action == OUT_SPEED_MOVEMENT || m_action == IN_SPEED_MOVEMENT) { |
| m_pos = pos; |
| moveSpeed(delta, m_action == IN_SPEED_MOVEMENT); |
| m_isImageChanged = true; |
| } |
| |
| if (m_action == RECT_SELECTION) { |
| int cpCount = m_controlPointEditorStroke.getControlPointCount(); |
| m_selectingRect.x0 = m_pos.x; |
| m_selectingRect.y0 = m_pos.y; |
| m_selectingRect.x1 = pos.x; |
| m_selectingRect.y1 = pos.y; |
| if (m_selectingRect.x0 > m_selectingRect.x1) |
| tswap(m_selectingRect.x1, m_selectingRect.x0); |
| if (m_selectingRect.y0 > m_selectingRect.y1) |
| tswap(m_selectingRect.y1, m_selectingRect.y0); |
| int i; |
| m_selection.selectNone(); |
| for (i = 0; i < cpCount; i++) |
| if (m_selectingRect.contains(m_controlPointEditorStroke.getControlPoint(i))) |
| m_selection.select(i); |
| } |
| |
| invalidate(); |
| } |
| |
| |
| |
| void ControlPointEditorTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e) |
| { |
| TVectorImageP vi(getImage(true)); |
| int currentStroke = m_controlPointEditorStroke.getStrokeIndex(); |
| if (!vi || currentStroke == -1) |
| return; |
| QMutexLocker lock(vi->getMutex()); |
| |
| if (m_action == EDIT_SEGMENT) { |
| m_moveControlPointEditorStroke.setStroke((TVectorImage *)0, -1); |
| TPointD delta = pos - m_pos; |
| moveSegment(delta, false, e.isShiftPressed()); |
| } |
| |
| if (m_action == RECT_SELECTION) { |
| if (m_selection.isEmpty()) { |
| |
| if (!TTool::getApplication()->getCurrentObject()->isSpline()) |
| m_controlPointEditorStroke.setStroke((TVectorImage *)0, -1); |
| m_action = NONE; |
| m_isImageChanged = false; |
| } else { |
| m_action = CP_MOVEMENT; |
| m_selection.makeCurrent(); |
| m_isImageChanged = false; |
| } |
| } |
| |
| if (m_action == NONE || !m_isImageChanged) { |
| m_undo = 0; |
| invalidate(); |
| return; |
| } |
| |
| notifyImageChanged(); |
| invalidate(); |
| |
| |
| if (m_undo) { |
| TUndoManager::manager()->add(m_undo); |
| m_undo = 0; |
| } |
| } |
| |
| |
| |
| void ControlPointEditorTool::addContextMenuItems(QMenu *menu) |
| { |
| m_isMenuViewed = true; |
| m_selection.addMenuItems(menu); |
| } |
| |
| |
| |
| void ControlPointEditorTool::linkSpeedInOut(int index) |
| { |
| if ((index == 0 || index == m_controlPointEditorStroke.getControlPointCount() - 1) && !m_controlPointEditorStroke.isSelfLoop()) |
| return; |
| if (m_action == IN_SPEED_MOVEMENT || m_action == CP_MOVEMENT) |
| m_controlPointEditorStroke.setCusp(index, false, true); |
| if (m_action == OUT_SPEED_MOVEMENT) |
| m_controlPointEditorStroke.setCusp(index, false, false); |
| invalidate(); |
| } |
| |
| |
| |
| void ControlPointEditorTool::unlinkSpeedInOut(int pointIndex) |
| { |
| m_controlPointEditorStroke.setCusp(pointIndex, true, true); |
| } |
| |
| |
| |
| bool ControlPointEditorTool::keyDown(int key, TUINT32 flags, const TPoint &pos) |
| { |
| TVectorImageP vi(getImage(true)); |
| if (!vi || (vi && m_selection.isEmpty())) |
| return false; |
| |
| |
| initUndo(); |
| |
| TPointD delta; |
| if (key == TwConsts::TK_UpArrow) |
| delta.y = 1; |
| else if (key == TwConsts::TK_DownArrow) |
| delta.y = -1; |
| else if (key == TwConsts::TK_LeftArrow) |
| delta.x = -1; |
| else if (key == TwConsts::TK_RightArrow) |
| delta.x = 1; |
| else |
| return false; |
| moveControlPoints(delta); |
| |
| invalidate(); |
| |
| TUndoManager::manager()->add(m_undo); |
| |
| return true; |
| } |
| |
| |
| |
| void ControlPointEditorTool::onEnter() |
| { |
| TVectorImageP vi(getImage(false)); |
| int currentStroke = m_controlPointEditorStroke.getStrokeIndex(); |
| if (m_isMenuViewed) { |
| m_isMenuViewed = false; |
| return; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
| |
| |
| |
| void ControlPointEditorTool::onLeave() |
| { |
| if (m_isMenuViewed) |
| return; |
| |
| } |
| |
| |
| |
| bool ControlPointEditorTool::onPropertyChanged(std::string propertyName) |
| { |
| AutoSelectDrawing = (int)(m_autoSelectDrawing.getValue()); |
| return true; |
| } |
| |
| |
| |
| void ControlPointEditorTool::onActivate() |
| { |
| |
| m_autoSelectDrawing.setValue(AutoSelectDrawing ? 1 : 0); |
| m_controlPointEditorStroke.setStroke((TVectorImage *)0, -1); |
| m_draw = true; |
| } |
| |
| |
| |
| void ControlPointEditorTool::onDeactivate() |
| { |
| m_draw = false; |
| } |
| |
| |
| |
| void ControlPointEditorTool::onImageChanged() |
| { |
| TVectorImageP vi(getImage(false)); |
| if (!vi) |
| return; |
| |
| int currentStroke = m_controlPointEditorStroke.getStrokeIndex(); |
| if (!vi || currentStroke == -1 || m_controlPointEditorStroke.getControlPointCount() == 0 || |
| vi->getStrokeCount() == 0 || (int)vi->getStrokeCount() <= currentStroke) { |
| m_controlPointEditorStroke.setStroke((TVectorImage *)0, -1); |
| return; |
| } else { |
| m_selection.selectNone(); |
| m_controlPointEditorStroke.setStroke(vi, currentStroke); |
| } |
| } |
| |
| |
| |
| int ControlPointEditorTool::getCursorId() const |
| { |
| switch (m_cursorType) { |
| case NORMAL: |
| return ToolCursor::SplineEditorCursor; |
| case ADD: |
| return ToolCursor::SplineEditorCursorAdd; |
| case EDIT_SPEED: |
| return ToolCursor::SplineEditorCursorSelect; |
| case EDIT_SEGMENT: |
| return ToolCursor::PinchCursor; |
| case NO_ACTIVE: |
| return ToolCursor::CURSOR_NO; |
| default: |
| return ToolCursor::SplineEditorCursor; |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |