Toshihiro Shimizu 890ddd
#include "rulertool.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tools/toolhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tscenehandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshlevelhandle.h"
Toshihiro Shimizu 890ddd
#include "tools/toolutils.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
#include "tools/cursors.h"
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "tgl.h"
Toshihiro Shimizu 890ddd
#include "toonz/stage2.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsimplelevel.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/icongenerator.h"
Toshihiro Shimizu 890ddd
#include "tenv.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tconst.h"
Toshihiro Shimizu 890ddd
#include "toonz/tframehandle.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
RulerTool::RulerTool()
Shinya Kitaoka 120a6e
    : TTool("T_Ruler")
Shinya Kitaoka 120a6e
    , m_firstPos(TConst::nowhere)
Shinya Kitaoka 120a6e
    , m_secondPos(TConst::nowhere)
Shinya Kitaoka 120a6e
    , m_mousePos(TConst::nowhere)
Shinya Kitaoka 120a6e
    , m_dragMode(MakeNewRuler)
Shinya Kitaoka 120a6e
    , m_justClicked(false) {
Shinya Kitaoka 120a6e
  bind(TTool::AllTargets);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RulerTool::setToolOptionsBox(RulerToolOptionsBox *toolOptionsBox) {
Shinya Kitaoka 120a6e
  m_toolOptionsBox.push_back(toolOptionsBox);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RulerTool::onImageChanged() {
Shinya Kitaoka 120a6e
  /*--位置をリセット--*/
Shinya Kitaoka 120a6e
  m_firstPos  = TConst::nowhere;
Shinya Kitaoka 120a6e
  m_secondPos = TConst::nowhere;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)m_toolOptionsBox.size(); i++) {
Shinya Kitaoka 120a6e
    m_toolOptionsBox[i]->resetValues();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RulerTool::draw() {
Shinya Kitaoka 120a6e
  /*--- 始点が設定されていたら、描画 ---*/
Shinya Kitaoka 120a6e
  if (m_firstPos != TConst::nowhere) {
Shinya Kitaoka 120a6e
    tglColor((m_dragMode == MoveFirstPos) ? TPixel32(51, 204, 26)
Shinya Kitaoka 120a6e
                                          : TPixel32::Red);
Shinya Kitaoka 120a6e
    tglDrawCircle(m_firstPos, 4);
Shinya Kitaoka 120a6e
    tglDrawCircle(m_firstPos, 2);
Shinya Kitaoka 120a6e
    /*--- 終点が設定されていたら、その区間を描画 ---*/
Shinya Kitaoka 120a6e
    if (m_secondPos != TConst::nowhere) {
Shinya Kitaoka 120a6e
      tglColor((m_dragMode == MoveRuler) ? TPixel32(51, 204, 26)
Shinya Kitaoka 120a6e
                                         : TPixel32::Red);
Shinya Kitaoka 120a6e
      glBegin(GL_LINE_STRIP);
Shinya Kitaoka 120a6e
      tglVertex(m_firstPos);
Shinya Kitaoka 120a6e
      tglVertex(m_secondPos);
Shinya Kitaoka 120a6e
      glEnd();
Shinya Kitaoka 120a6e
      tglColor((m_dragMode == MoveSecondPos) ? TPixel32(51, 204, 26)
Shinya Kitaoka 120a6e
                                             : TPixel32::Red);
Shinya Kitaoka 120a6e
      tglDrawCircle(m_secondPos, 4);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RulerTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  if (m_dragMode == MakeNewRuler) m_justClicked = true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RulerTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  /*-- 最初のドラッグ --*/
Shinya Kitaoka 120a6e
  if (m_justClicked && m_dragMode == MakeNewRuler) {
Shinya Kitaoka 120a6e
    m_firstPos    = m_mousePos;
Shinya Kitaoka 120a6e
    m_justClicked = false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*-- ドラッグモードがMakeNewRuler/MoveSecondPosのとき、secondPosを更新 --*/
Shinya Kitaoka 120a6e
  if (m_dragMode == MakeNewRuler || m_dragMode == MoveSecondPos) {
Shinya Kitaoka 120a6e
    /*-- Shiftキーが押されていたら:0,45,90度に角度固定の直線を引く --*/
Shinya Kitaoka 120a6e
    if (e.isShiftPressed())
Shinya Kitaoka 120a6e
      m_secondPos = getHVCoordinatedPos(pos, m_firstPos);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      m_secondPos = pos;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*-- ドラッグモードがMoveFirstPosのとき、firstPosを更新 --*/
Shinya Kitaoka 120a6e
  else if (m_dragMode == MoveFirstPos) {
Shinya Kitaoka 120a6e
    /*-- Shiftキーが押されていたら:0,45,90度に角度固定の直線を引く --*/
Shinya Kitaoka 120a6e
    if (e.isShiftPressed())
Shinya Kitaoka 120a6e
      m_firstPos = getHVCoordinatedPos(pos, m_secondPos);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      m_firstPos = pos;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*-- Ruler全体を移動するモード --*/
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    TPointD d = pos - m_mousePos;
Shinya Kitaoka 120a6e
    m_firstPos += d;
Shinya Kitaoka 120a6e
    m_secondPos += d;
Shinya Kitaoka 120a6e
    /*-- マウス位置を更新 --*/
Shinya Kitaoka 120a6e
    m_mousePos = pos;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  updateToolOption(); /*-- ToolOptionの表示を更新 --*/
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RulerTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_justClicked = false;
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RulerTool::mouseMove(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  /*-- マウス位置を更新 --*/
Shinya Kitaoka 120a6e
  m_mousePos = pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*-- マウスクリックしてたら無視 --*/
Shinya Kitaoka 120a6e
  if (e.isLeftButtonPressed()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*--
Shinya Kitaoka 120a6e
   * マウスがRulerの端点/Rulerそのものに近い場合はドラッグモードを変更する。--*/
Shinya Kitaoka 120a6e
  if (m_firstPos != TConst::nowhere && tdistance2(pos, m_firstPos) < 16)
Shinya Kitaoka 120a6e
    m_dragMode = MoveFirstPos;
Shinya Kitaoka 120a6e
  else if (m_secondPos != TConst::nowhere && tdistance2(pos, m_secondPos) < 16)
Shinya Kitaoka 120a6e
    m_dragMode = MoveSecondPos;
Shinya Kitaoka 120a6e
  else if (isNearRuler())
Shinya Kitaoka 120a6e
    m_dragMode = MoveRuler;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    m_dragMode = MakeNewRuler;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RulerTool::onActivate() {
Shinya Kitaoka 120a6e
  /*-- 位置をリセット --*/
Shinya Kitaoka 120a6e
  m_firstPos  = TConst::nowhere;
Shinya Kitaoka 120a6e
  m_secondPos = TConst::nowhere;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)m_toolOptionsBox.size(); i++) {
Shinya Kitaoka 120a6e
    m_toolOptionsBox[i]->resetValues();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int RulerTool::getCursorId() const {
Shinya Kitaoka 120a6e
  if (m_dragMode == MakeNewRuler)
Shinya Kitaoka 120a6e
    return ToolCursor::RulerNewCursor;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return ToolCursor::RulerModifyCursor;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*-- ToolOptionの表示を更新 --*/
Shinya Kitaoka 120a6e
void RulerTool::updateToolOption() {
Shinya Kitaoka 120a6e
  TTool::Application *app    = TTool::getApplication();
Shinya Kitaoka 120a6e
  TFrameHandle *currentFrame = app->getCurrentFrame();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double x, y, w, h, a, l;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*--
Shinya Kitaoka 120a6e
   * Level編集モードのとき、そのLevelのDPIに合わせてInchの値を得る。Pixelの値も出力する。
Shinya Kitaoka 120a6e
   * --*/
Shinya Kitaoka 120a6e
  if (currentFrame->isEditingLevel()) {
Shinya Kitaoka 120a6e
    TXshLevelHandle *currentLevel = app->getCurrentLevel();
Shinya Kitaoka 120a6e
    TXshLevel *xl                 = currentLevel->getLevel();
Shinya Kitaoka 120a6e
    if (xl) {
Shinya Kitaoka 120a6e
      TXshSimpleLevel *sl = xl->getSimpleLevel();
Shinya Kitaoka 120a6e
      if (sl) {
Shinya Kitaoka 120a6e
        int subsampling = sl->getImageSubsampling(getCurrentFid());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        TPointD dpiScale = getViewer()->getDpiScale();
Shinya Kitaoka 120a6e
        TPointD pp1 =
Shinya Kitaoka 120a6e
            TPointD(m_firstPos.x / dpiScale.x, m_firstPos.y / dpiScale.y);
Shinya Kitaoka 120a6e
        TPointD pp2 =
Shinya Kitaoka 120a6e
            TPointD(m_secondPos.x / dpiScale.x, m_secondPos.y / dpiScale.y);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        TPointD p1 = TScale(1.0 / subsampling) * pp1 + TPointD(-0.5, -0.5);
Shinya Kitaoka 120a6e
        TPointD p2 = TScale(1.0 / subsampling) * pp2 + TPointD(-0.5, -0.5);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        TImageP image = getImage(false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        TPoint pix1, pix2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        TToonzImageP ti  = image;
Shinya Kitaoka 120a6e
        TRasterImageP ri = image;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (ti || ri) {
Shinya Kitaoka 120a6e
          if (ti) {
Shinya Kitaoka 120a6e
            TDimension size = ti->getSize();
Shinya Kitaoka 120a6e
            pix1            = TPoint(tround(0.5 * size.lx + p1.x),
Shinya Kitaoka 120a6e
                          tround(0.5 * size.ly + p1.y));
Shinya Kitaoka 120a6e
            pix2 = TPoint(tround(0.5 * size.lx + p2.x),
Shinya Kitaoka 120a6e
                          tround(0.5 * size.ly + p2.y));
Shinya Kitaoka 120a6e
          } else if (ri) {
Shinya Kitaoka 120a6e
            TDimension size = ri->getRaster()->getSize();
Shinya Kitaoka 120a6e
            pix1            = TPoint(tround(0.5 * size.lx + p1.x),
Shinya Kitaoka 120a6e
                          tround(0.5 * size.ly + p1.y));
Shinya Kitaoka 120a6e
            pix2 = TPoint(tround(0.5 * size.lx + p2.x),
Shinya Kitaoka 120a6e
                          tround(0.5 * size.ly + p2.y));
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          int xPix, yPix, wPix, hPix;
Shinya Kitaoka 120a6e
          TPointD dpi = sl->getDpi(getCurrentFid());
Shinya Kitaoka 120a6e
          xPix        = pix1.x;
Shinya Kitaoka 120a6e
          yPix        = pix1.y;
Shinya Kitaoka 120a6e
          wPix        = pix2.x - pix1.x;
Shinya Kitaoka 120a6e
          hPix        = pix2.y - pix1.y;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          x = (double)xPix / dpi.x;
Shinya Kitaoka 120a6e
          y = (double)yPix / dpi.y;
Shinya Kitaoka 120a6e
          w = (double)wPix / dpi.x;
Shinya Kitaoka 120a6e
          h = (double)hPix / dpi.y;
Shinya Kitaoka 120a6e
          a = atan2(h, w) * 180.0 / 3.14159264;
Shinya Kitaoka 120a6e
          l = sqrt(w * w + h * h);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          for (int i = 0; i < (int)m_toolOptionsBox.size(); i++) {
Shinya Kitaoka 120a6e
            m_toolOptionsBox[i]->updateValues(true, x, y, w, h, a, l, xPix,
Shinya Kitaoka 120a6e
                                              yPix, wPix, hPix);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          return;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*-- シーン編集モードのとき、Stage::inchで割った値がInch値となる --*/
Shinya Kitaoka 120a6e
  x = m_firstPos.x / Stage::inch;
Shinya Kitaoka 120a6e
  y = m_firstPos.y / Stage::inch;
Shinya Kitaoka 120a6e
  w = (m_secondPos.x - m_firstPos.x) / Stage::inch;
Shinya Kitaoka 120a6e
  h = (m_secondPos.y - m_firstPos.y) / Stage::inch;
Shinya Kitaoka 120a6e
  a = atan2(h, w) * 180.0 / 3.14159264;
Shinya Kitaoka 120a6e
  l = sqrt(w * w + h * h);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)m_toolOptionsBox.size(); i++) {
Shinya Kitaoka 120a6e
    m_toolOptionsBox[i]->updateValues(false, x, y, w, h, a, l);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! 現在のマウス位置がRulerに十分近ければTrueを返す
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
bool RulerTool::isNearRuler() {
Shinya Kitaoka 120a6e
  double a, b, c;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPointD vec = m_secondPos - m_firstPos;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  a = -vec.y;
Shinya Kitaoka 120a6e
  b = vec.x;
Shinya Kitaoka 120a6e
  c = -a * m_firstPos.x - b * m_firstPos.y;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double k  = a * m_mousePos.x + b * m_mousePos.y + c;
Shinya Kitaoka 120a6e
  double d2 = k * k / (a * a + b * b);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*-- 距離が4より遠ければfalse --*/
Shinya Kitaoka 120a6e
  if (d2 > 16) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*--
Shinya Kitaoka 120a6e
   * 垂線の足がRuler上にあるかを判断。Rulerを対角線とするRectにマウス位置が収まるかどうか
Shinya Kitaoka 120a6e
   * --*/
Shinya Kitaoka 120a6e
  TRectD rect = TRectD(m_firstPos, m_secondPos).enlarge(4);
Shinya Kitaoka 120a6e
  return rect.contains(m_mousePos);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! 基準点に対し、マウス位置を0,45,90度にフィットさせた位置を返す
Shinya Kitaoka 120a6e
        斜め方向では、X/Yの値のうち絶対値の小さいほうに合わせる。
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------------------
Shinya Kitaoka 120a6e
TPointD RulerTool::getHVCoordinatedPos(TPointD p, TPointD centerPos) {
Shinya Kitaoka 120a6e
  TPointD vec = p - centerPos;
Shinya Kitaoka 120a6e
  double degree =
Shinya Kitaoka 120a6e
      (vec.x == 0.0) ? 90.0 : atan(vec.y / vec.x) * 180.0 / 3.1415926536;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD outPoint;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (degree <= -67.5) /*--垂直--*/
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    outPoint.x = centerPos.x;
Shinya Kitaoka 120a6e
    outPoint.y = p.y;
Shinya Kitaoka 120a6e
  } else if (degree < -22.5) /*--右斜め下--*/
Shinya Kitaoka 120a6e
  {
Rozhuk Ivan 823a31
    if (std::abs(vec.x) > std::abs(vec.y))
Shinya Kitaoka 120a6e
      outPoint = centerPos + TPointD(-vec.y, vec.y);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      outPoint = centerPos + TPointD(vec.x, -vec.x);
Shinya Kitaoka 120a6e
  } else if (degree <= 22.5) /*--水平--*/
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    outPoint.x = p.x;
Shinya Kitaoka 120a6e
    outPoint.y = centerPos.y;
Shinya Kitaoka 120a6e
  } else if (degree < 67.5) /*--右斜め上--*/
Shinya Kitaoka 120a6e
  {
Rozhuk Ivan 823a31
    if (std::abs(vec.x) > std::abs(vec.y))
Shinya Kitaoka 120a6e
      outPoint = centerPos + TPointD(vec.y, vec.y);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      outPoint = centerPos + TPointD(vec.x, vec.x);
Shinya Kitaoka 120a6e
  } else /*--再び垂直--*/
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    outPoint.x = centerPos.x;
Shinya Kitaoka 120a6e
    outPoint.y = p.y;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return outPoint;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
RulerTool RulerTool;