Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//  pinchtool.cpp
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//  ChangeLog:
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//    24/04/2005  Fab
Toshihiro Shimizu 890ddd
//                  Refactoring:
Toshihiro Shimizu 890ddd
//                    - removed unused headers
Toshihiro Shimizu 890ddd
//                    - changed zero finder algorithm (secant vs bisection)
Toshihiro Shimizu 890ddd
//    22/05/2005  Fab
Toshihiro Shimizu 890ddd
//                  Added header file.
Toshihiro Shimizu 890ddd
//                  Added adapting dragger.
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//    12/06/2005  Fab
Toshihiro Shimizu 890ddd
//                  Changed deformator API.
Toshihiro Shimizu 890ddd
//                  Added designer for dragger.
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
#define _STLP_DEBUG 1
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tools/toolutils.h"
Toshihiro Shimizu 890ddd
#include "tools/toolhandle.h"
Toshihiro Shimizu 890ddd
#include "tools/cursors.h"
Toshihiro Shimizu 890ddd
#include "tdebugmessage.h"
Toshihiro Shimizu 890ddd
#include "tgeometry.h"
Toshihiro Shimizu 890ddd
#include "tgl.h"
Toshihiro Shimizu 890ddd
#include "tproperty.h"
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
#include "tstrokeutil.h"
Toshihiro Shimizu 890ddd
#include "tthreadmessage.h"
Toshihiro Shimizu 890ddd
#include "tools/pinchtool.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/tobjecthandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshlevelhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobject.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "ext/StrokeDeformation.h"
Toshihiro Shimizu 890ddd
#include "ext/SmoothDeformation.h"
Toshihiro Shimizu 890ddd
#include "ext/OverallDesigner.h"
Toshihiro Shimizu 890ddd
#include "ext/ExtUtil.h"
Toshihiro Shimizu 890ddd
#include "ext/Selector.h"
Toshihiro Shimizu 890ddd
#include "ext/CornerDeformation.h"
Toshihiro Shimizu 890ddd
#include "ext/StraightCornerDeformation.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <memory></memory>
Shinya Kitaoka c12eac
#include <algorithm></algorithm>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace ToolUtils;
Toshihiro Shimizu 890ddd
using namespace ToonzExt;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// viene usato??
Toshihiro Shimizu 890ddd
class TGlobalChange;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct GLMatrixGuard {
Shinya Kitaoka 120a6e
  GLMatrixGuard() { glPushMatrix(); }
Shinya Kitaoka 120a6e
  ~GLMatrixGuard() { glPopMatrix(); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PinchTool::PinchTool()
Shinya Kitaoka 120a6e
    : TTool("T_Pinch")
Shinya Kitaoka 120a6e
    , m_active(false)
Shinya Kitaoka 120a6e
    , m_cursorEnabled(false)
Shinya Kitaoka 120a6e
    , m_draw(false)
Shinya Kitaoka 120a6e
    , m_undo(0)
Shinya Kitaoka 120a6e
    , m_showSelector(true)
shun-iwasawa 1c6241
    , m_toolRange("Size:", 1.0, 10000.0, 500.0)  // W_ToolOptions_PinchTool
Shinya Kitaoka 120a6e
    , m_toolCornerSize("Corner:", 1.0, 180.0,
Shinya Kitaoka 120a6e
                       160.0)          // W_ToolOptions_PinchCorner
Shinya Kitaoka 120a6e
    , m_autoOrManual("Manual", false)  // W_ToolOptions_PinchManual
Shinya Kitaoka 120a6e
    , m_deformation(new ToonzExt::StrokeDeformation)
Shinya Kitaoka 120a6e
    , m_selector(500, 10, 1000) {
Shinya Kitaoka 120a6e
  bind(TTool::Vectors);
Shinya Kitaoka 120a6e
shun-iwasawa 76d093
  m_toolRange.setNonLinearSlider();
shun-iwasawa 76d093
Shinya Kitaoka 120a6e
  m_prop.bind(m_toolCornerSize);
Shinya Kitaoka 120a6e
  m_prop.bind(m_autoOrManual);
Shinya Kitaoka 120a6e
  m_prop.bind(m_toolRange);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  CornerDeformation::instance()->setCursorId(ToolCursor::PinchWaveCursor);
Shinya Kitaoka 120a6e
  SmoothDeformation::instance()->setCursorId(ToolCursor::PinchCursor);
Shinya Kitaoka 120a6e
  StraightCornerDeformation::instance()->setCursorId(
Shinya Kitaoka 120a6e
      ToolCursor::PinchAngleCursor);
Shinya Kitaoka 120a6e
  assert(m_deformation && "Can not create a deformation CATASTROFIC!!!");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TMouseEvent dummy;
Shinya Kitaoka 120a6e
  updateInterfaceStatus(dummy);
Shinya Kitaoka 120a6e
  m_autoOrManual.setId("Manual");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PinchTool::~PinchTool() {
Shinya Kitaoka 120a6e
  delete m_deformation;
Shinya Kitaoka 120a6e
  m_deformation = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PinchTool::updateTranslation() {
Shinya Kitaoka 120a6e
  m_toolRange.setQStringName(tr("Size:"));
Shinya Kitaoka 120a6e
  m_toolCornerSize.setQStringName(tr("Corner:"));
Shinya Kitaoka 120a6e
  m_autoOrManual.setQStringName(tr("Manual"));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStroke *PinchTool::getClosestStroke(const TPointD &pos, double &w) const {
Shinya Kitaoka 120a6e
  TVectorImageP vi = TImageP(getImage(false));
Shinya Kitaoka 120a6e
  if (!vi) return 0;
Shinya Kitaoka 120a6e
  double dist = 0;
Shinya Kitaoka 120a6e
  UINT index;
Shinya Kitaoka 120a6e
  if (vi->getNearestStroke(pos, w, index, dist, true))
Shinya Kitaoka 120a6e
    return vi->getStroke(index);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PinchTool::updateInterfaceStatus(const TMouseEvent &event) {
Shinya Kitaoka 120a6e
  assert(getPixelSize() > 0 && "Pixel size is lower than 0!!!");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_status.isManual_            = m_autoOrManual.getValue();
Shinya Kitaoka 120a6e
  m_status.pixelSize_           = getPixelSize();
Shinya Kitaoka 120a6e
  m_status.cornerSize_          = (int)m_toolCornerSize.getValue();
Shinya Kitaoka 120a6e
  m_status.lengthOfAction_      = m_toolRange.getValue();
Campbell Barton f49389
  m_status.deformerSensitivity_ = 0.01 * getPixelSize();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_status.key_event_ = ContextStatus::NONE;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // mutual exclusive
shun-iwasawa 76d093
  if (event.isCtrlPressed()) m_status.key_event_ = ContextStatus::CTRL;
Shinya Kitaoka 120a6e
  if (event.isShiftPressed()) m_status.key_event_ = ContextStatus::SHIFT;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // TODO:  **DEVE** essere fatto dentro la costruzione di TMouseEvent
Shinya Kitaoka 120a6e
  // nel codice di Toonz/Tab/ecc. **NON** ci devono essere ifdef MACOSX se e'
Shinya Kitaoka 120a6e
  // possibile
Shinya Kitaoka 120a6e
  // evitarlo. Qua sotto ci deve essere solo if(event.isShiftPressed)
Shinya Kitaoka 120a6e
  /*#ifdef MACOSX
Shinya Kitaoka 120a6e
if(event.isLockPressed() )
Toshihiro Shimizu 890ddd
#else*/
Shinya Kitaoka 120a6e
  if (event.isAltPressed())
Shinya Kitaoka 120a6e
    //#endif
Shinya Kitaoka 120a6e
    m_status.key_event_ = ContextStatus::ALT;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_selector.setStroke(0);
Shinya Kitaoka 120a6e
  m_selector.setVisibility(m_status.isManual_ && m_showSelector);
Shinya Kitaoka 120a6e
  m_selector.setLength(m_status.lengthOfAction_);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PinchTool::updateStrokeStatus(TStroke *stroke, double w) {
Shinya Kitaoka 120a6e
  assert(stroke && "Stroke is null!!!");
Shinya Kitaoka 120a6e
  assert(0.0 <= w && w <= 1.0 && "Stroke's parameter is out of range [0,1]!!!");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!stroke || w < 0.0 || w > 1.0) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // start update the status
Shinya Kitaoka 120a6e
  m_status.stroke2change_ = stroke;
Shinya Kitaoka 120a6e
  m_status.w_             = w;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(stroke->getLength() >= 0.0 && "Wrong length in stroke!!!");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int PinchTool::updateCursor() const {
manongjohn 40a40e
  if (m_viewer && m_viewer->getGuidedStrokePickerMode())
manongjohn 40a40e
    return m_viewer->getGuidedStrokePickerCursor();
manongjohn 40a40e
Shinya Kitaoka 120a6e
  if (!(TVectorImageP)getImage(false)) return ToolCursor::CURSOR_NO;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return m_deformation->getCursorId();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PinchTool::leftButtonDown(const TPointD &pos, const TMouseEvent &event) {
manongjohn 40a40e
  if (getViewer() && getViewer()->getGuidedStrokePickerMode()) {
manongjohn 40a40e
    getViewer()->doPickGuideStroke(pos);
manongjohn 40a40e
    return;
manongjohn 40a40e
  }
manongjohn 40a40e
Shinya Kitaoka 120a6e
  m_curr = m_down = pos;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_active && !m_selector.isSelected()) {
Shinya Kitaoka 120a6e
    m_active = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    assert(m_undo == 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    StrokeDeformation *deformation = m_deformation;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TVectorImageP vi = TImageP(getImage(true));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (!vi) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_active = true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    ContextStatus *status = &m_status;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // reset status
Shinya Kitaoka 120a6e
    status->init();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    double w, dist2;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // find nearest stroke
Shinya Kitaoka 120a6e
    if (vi->getNearestStroke(m_down, w, m_n, dist2, true)) {
Shinya Kitaoka 120a6e
      TStroke *stroke = vi->getStroke(m_n);
Shinya Kitaoka 120a6e
      assert(stroke && "Not valid stroke found!!!");
Shinya Kitaoka 120a6e
      if (!stroke) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      updateStrokeStatus(stroke, w);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      // set parameters from sliders
Shinya Kitaoka 120a6e
      updateInterfaceStatus(event);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      deformation->activate(status);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      // stroke can be changed (replaced by another) during deformation activate
Shinya Kitaoka 120a6e
      if (TTool::getApplication()->getCurrentObject()->isSpline())
Shinya Kitaoka 120a6e
        m_undo = new ToolUtils::UndoPath(
Shinya Kitaoka 120a6e
            getXsheet()->getStageObject(getObjectId())->getSpline());
Shinya Kitaoka 120a6e
      else {
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
        m_undo      = new UndoModifyStrokeAndPaint(sl, id, m_n);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_selector.mouseDown(m_curr);
Shinya Kitaoka 120a6e
  m_prev = m_curr;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PinchTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_curr = pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_selector.isSelected()) {
Shinya Kitaoka 120a6e
    m_selector.mouseDrag(m_curr);
Shinya Kitaoka 120a6e
    TDoubleProperty::Range prop_range = m_toolRange.getRange();
Shinya Kitaoka 120a6e
    double val_in_range               = m_selector.getLength();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // set value in range
Shinya Kitaoka 120a6e
    val_in_range =
Shinya Kitaoka 120a6e
        std::max(std::min(val_in_range, prop_range.second), prop_range.first);
Shinya Kitaoka 120a6e
    try {
Shinya Kitaoka 120a6e
      m_toolRange.setValue(val_in_range);
Shinya Kitaoka 120a6e
      TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Shinya Kitaoka 120a6e
    } catch (TDoubleProperty::RangeError &) {
Shinya Kitaoka 120a6e
      m_toolRange.setValue((prop_range.first + prop_range.second) * 0.5);
Shinya Kitaoka 120a6e
      TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_selector.setLength(m_toolRange.getValue());
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    TVectorImageP vi(getImage(true));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ContextStatus *status = &m_status;
Shinya Kitaoka 120a6e
    if (!vi || !status->stroke2change_ || !m_active) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    QMutexLocker lock(vi->getMutex());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // assert( status->stroke2change_->getLength() >= 0.0 );
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    StrokeDeformation *deformation = m_deformation;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPointD delta = m_curr - m_prev;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    deformation->update(delta);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_prev = m_curr;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // moveCursor(pos);
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PinchTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  if (!m_active || m_selector.isSelected()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_active = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TVectorImageP vi(getImage(true));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ContextStatus *status = &m_status;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!vi || !status->stroke2change_) {
Shinya Kitaoka 120a6e
    delete m_undo;
Shinya Kitaoka 120a6e
    m_undo = 0;
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // if mouse position is unchanged doesn't modify current stroke
Shinya Kitaoka 120a6e
  if (areAlmostEqual(m_down, pos, PickRadius * status->pixelSize_)) {
Shinya Kitaoka 120a6e
    assert(m_undo);
Shinya Kitaoka 120a6e
    delete m_undo;
Shinya Kitaoka 120a6e
    m_undo = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// to avoid red line tool on stroke
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Shinya Kitaoka 120a6e
    invalidate(
Shinya Kitaoka 120a6e
        status->stroke2change_->getBBox().enlarge(status->pixelSize_ * 13));
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
    invalidate();
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
    m_deformation->deactivate();
Shinya Kitaoka 120a6e
    status->stroke2change_ = 0;
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QMutexLocker lock(vi->getMutex());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TStroke *deactivateStroke          = m_deformation->deactivate();
Shinya Kitaoka 120a6e
  deactivateStroke->outlineOptions() = status->stroke2change_->outlineOptions();
Shinya Kitaoka 120a6e
  replaceStroke(status->stroke2change_, deactivateStroke, m_n, vi);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  status->stroke2change_ = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  vi->notifyChangedStrokes(m_n);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
  vi->checkIntersections();
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
  vi->checkIntersections();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  moveCursor(pos);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  notifyImageChanged();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(m_undo);
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(m_undo);
Shinya Kitaoka 120a6e
  m_undo = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PinchTool::onEnter() {
Shinya Kitaoka 120a6e
  m_draw = true;
Shinya Kitaoka 120a6e
  // per sicurezza
Shinya Kitaoka 120a6e
  // m_status.stroke2change_ = 0;
Shinya Kitaoka 120a6e
  // m_selector.setStroke(0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PinchTool::onLeave() {
shun-iwasawa 76d093
  if (!m_active) m_draw = false;
Shinya Kitaoka 120a6e
  m_status.stroke2change_ = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Abbiamo dovuto commentarlo perche' stranamente
Shinya Kitaoka 120a6e
  // l'onLeave viene chiamata anche quando viene premuto il tasto del mouse
Shinya Kitaoka 120a6e
  // per iniziare a fare drag utilizzando il Selector
Shinya Kitaoka 120a6e
  // setStroke al suo interno resetta lo status del Selector (lo mette a NONE)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  m_selector.setStroke(0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_deformation->reset();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PinchTool::onImageChanged() {
Shinya Kitaoka 120a6e
  m_status.stroke2change_ = 0;
Shinya Kitaoka 120a6e
  m_deformation->reset();
shun-iwasawa d8eb6b
  // m_active may be true if the frame switched while dragging
shun-iwasawa d8eb6b
  if (m_active) {
shun-iwasawa d8eb6b
    m_deformation->deactivate();
shun-iwasawa d8eb6b
    m_active = false;
shun-iwasawa d8eb6b
    if (m_undo) {
shun-iwasawa d8eb6b
      delete m_undo;
shun-iwasawa d8eb6b
      m_undo = 0;
shun-iwasawa d8eb6b
    }
shun-iwasawa d8eb6b
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double w        = 0;
shun_iwasawa bc352c
  TStroke *stroke = getClosestStroke(m_lastMouseEvent.m_pos, w);
Shinya Kitaoka 120a6e
  if (stroke) {
Shinya Kitaoka 120a6e
    // set parameters from sliders
Shinya Kitaoka 120a6e
    updateInterfaceStatus(m_lastMouseEvent);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // update information about current stroke
Shinya Kitaoka 120a6e
    updateStrokeStatus(stroke, w);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_selector.setStroke(stroke);
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PinchTool::draw() {
Shinya Kitaoka 120a6e
  GLMatrixGuard guard;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TVectorImageP img(getImage(true));
Shinya Kitaoka 120a6e
  if (!img ||
Shinya Kitaoka 120a6e
      img->getStrokeCount() ==
Shinya Kitaoka 120a6e
          0)  // Controllo che il numero degli stroke nell'immagine sia != 0
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  if (!m_draw) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ContextStatus *status = &m_status;
Shinya Kitaoka 120a6e
  if (!status) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  StrokeDeformation *deformation = m_deformation;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  OverallDesigner designer((int)m_curr.x, (int)m_curr.y);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // m_active == true means that a button down is done (drag)
Shinya Kitaoka 120a6e
  if (!m_active) {
Shinya Kitaoka 120a6e
    if (m_cursorEnabled) {
Shinya Kitaoka 120a6e
      glColor3d(1, 0, 1);
Shinya Kitaoka 120a6e
      if (m_cursor.thick > 0) tglDrawCircle(m_cursor, m_cursor.thick);
Shinya Kitaoka 120a6e
      tglDrawCircle(m_cursor, m_cursor.thick + 4 * status->pixelSize_);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // internal deformer can be changed during draw
Shinya Kitaoka 120a6e
  if (!m_selector.isSelected()) deformation->draw(&designer);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_selector.draw(&designer);
Shinya Kitaoka 120a6e
  CHECK_ERRORS_BY_GL;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PinchTool::invalidateCursorArea() {
Shinya Kitaoka 120a6e
  double r = m_cursor.thick + 6;
Shinya Kitaoka 120a6e
  TPointD d(r, r);
Shinya Kitaoka 120a6e
  invalidate(TRectD(m_cursor - d, m_cursor + d));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PinchTool::mouseMove(const TPointD &pos, const TMouseEvent &event) {
Shinya Kitaoka 120a6e
  if (m_active) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_draw) m_draw = true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ContextStatus *status = &m_status;
Shinya Kitaoka 120a6e
  m_curr                = pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const int pixelRange = 3;
Rozhuk Ivan 823a31
  if (std::abs(m_lastMouseEvent.m_pos.x - event.m_pos.x) < pixelRange &&
Rozhuk Ivan 823a31
      std::abs(m_lastMouseEvent.m_pos.y - event.m_pos.y) < pixelRange &&
Shinya Kitaoka 120a6e
      m_lastMouseEvent.getModifiersMask() == event.getModifiersMask())
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_lastMouseEvent = event;
Shinya Kitaoka 120a6e
  double w         = 0;
Shinya Kitaoka 120a6e
  TStroke *stroke  = getClosestStroke(pos, w);
Shinya Kitaoka 120a6e
  if (stroke) {
Shinya Kitaoka 120a6e
    // set parameters from sliders
Shinya Kitaoka 120a6e
    updateInterfaceStatus(event);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // update information about current stroke
Shinya Kitaoka 120a6e
    updateStrokeStatus(stroke, w);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // retrieve the currect m_deformation and
Shinya Kitaoka 120a6e
    // prepare to design and modify
Shinya Kitaoka 120a6e
    if (m_deformation) m_deformation->check(status);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_selector.setStroke(stroke);
Shinya Kitaoka 120a6e
    m_selector.mouseMove(m_curr);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    m_status.stroke2change_ = 0;
Shinya Kitaoka 120a6e
    m_selector.setStroke(0);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_prev          = m_curr;
Shinya Kitaoka 120a6e
  m_cursorEnabled = moveCursor(pos);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_cursorEnabled) invalidate();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TNotifier::instance()->notify(TToolChange());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
shun-iwasawa 7f1e30
bool PinchTool::keyDown(QKeyEvent *event) {
Shinya Kitaoka 120a6e
  if (!m_active) m_deformation->reset();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if 0
Toshihiro Shimizu 890ddd
  char c = (char)key;
Toshihiro Shimizu 890ddd
  if(c == 'p' ||
Toshihiro Shimizu 890ddd
     c == 'P' )
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    TVectorImageP vimage(getImage());      
Toshihiro Shimizu 890ddd
    if(!vimage)
Toshihiro Shimizu 890ddd
      return false;
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
    char  fileName[] = {"c:\\toonz_input.sdd"};
Toshihiro Shimizu 890ddd
    ofstream  out_file(fileName);
Toshihiro Shimizu 890ddd
    if(!out_file)
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
      cerr<<"Error on opening: "<
Toshihiro Shimizu 890ddd
      return false;
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
    out_file<<"# VImage info\n";
Toshihiro Shimizu 890ddd
    out_file<<"# Number of stroke:\n";
Toshihiro Shimizu 890ddd
    const int max_number_of_strokes = vimage->getStrokeCount();
Toshihiro Shimizu 890ddd
    out_file<
Toshihiro Shimizu 890ddd
    int number_of_strokes = 0;
Toshihiro Shimizu 890ddd
    const int cp_for_row=3;
Toshihiro Shimizu 890ddd
    while( number_of_strokes
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
      TStroke* ref = vimage->getStroke(number_of_strokes);
Toshihiro Shimizu 890ddd
      out_file<
Toshihiro Shimizu 890ddd
      out_file<<"# Number of control points for stroke:\n";
Toshihiro Shimizu 890ddd
      const int max_number_of_cp = ref->getControlPointCount();
Toshihiro Shimizu 890ddd
      out_file<
Toshihiro Shimizu 890ddd
      out_file<<"# Control Points:\n";
Toshihiro Shimizu 890ddd
      int number_of_cp=0;
Toshihiro Shimizu 890ddd
      while( number_of_cp
Toshihiro Shimizu 890ddd
      {
Toshihiro Shimizu 890ddd
        out_file<<ref->getControlPoint(number_of_cp)<<" ";</ref->
Toshihiro Shimizu 890ddd
        if(!((number_of_cp+1)%cp_for_row)) // add a new line after ten points
Toshihiro Shimizu 890ddd
          out_file<
Toshihiro Shimizu 890ddd
        number_of_cp++;
Toshihiro Shimizu 890ddd
      }
Toshihiro Shimizu 890ddd
      out_file<
Toshihiro Shimizu 890ddd
      number_of_strokes++;
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
#endif
shun-iwasawa d8eb6b
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool PinchTool::moveCursor(const TPointD &pos) {
Shinya Kitaoka 120a6e
  double w        = 0.0;
Shinya Kitaoka 120a6e
  TStroke *stroke = getClosestStroke(pos, w);
Shinya Kitaoka 120a6e
  if (!stroke) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_cursor = stroke->getThickPoint(w);
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PinchTool::onActivate() {
Shinya Kitaoka 120a6e
  //  getApplication()->editImageOrSpline();
Shinya Kitaoka 120a6e
  //  TNotifier::instance()->attach(this);
Shinya Kitaoka 120a6e
  // per sicurezza
Shinya Kitaoka 120a6e
  m_status.stroke2change_ = 0;
Shinya Kitaoka 120a6e
  m_selector.setStroke(0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PinchTool::onDeactivate() {
Shinya Kitaoka 120a6e
  m_draw = false;
Shinya Kitaoka 120a6e
  delete m_undo;
Shinya Kitaoka 120a6e
  m_undo   = 0;
Shinya Kitaoka 120a6e
  m_active = false;
Shinya Kitaoka 120a6e
  m_deformation->reset();
Shinya Kitaoka 120a6e
  //  TNotifier::instance()->detach(this);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PinchTool::update(const TGlobalChange &) {
Shinya Kitaoka 120a6e
  m_cursor = TConsts::natp;
Shinya Kitaoka 120a6e
  m_selector.setStroke(0);
Shinya Kitaoka 120a6e
  m_selector.setVisibility(m_autoOrManual.getValue() && m_showSelector);
Shinya Kitaoka 120a6e
  if (m_deformation) delete m_deformation->deactivate();
Shinya Kitaoka 120a6e
  // per sicurezza
Shinya Kitaoka 120a6e
  m_status.stroke2change_ = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static PinchTool pinchTool;