Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Finger Tool : 線のノイズを埋めるツール
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
#include "tools/toolutils.h"
Toshihiro Shimizu 890ddd
#include "tools/tool.h"
Toshihiro Shimizu 890ddd
#include "tmathutil.h"
Toshihiro Shimizu 890ddd
#include "tools/cursors.h"
Toshihiro Shimizu 890ddd
#include "drawutil.h"
Toshihiro Shimizu 890ddd
#include "tcolorstyles.h"
Toshihiro Shimizu 890ddd
#include "tundo.h"
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
#include "tproperty.h"
Toshihiro Shimizu 890ddd
#include "toonz/strokegenerator.h"
Toshihiro Shimizu 890ddd
#include "toonz/ttilesaver.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsimplelevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/observer.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzimageutils.h"
Toshihiro Shimizu 890ddd
#include "toonz/levelproperties.h"
Toshihiro Shimizu 890ddd
#include "toonz/stage2.h"
Toshihiro Shimizu 890ddd
#include "toonz/ttileset.h"
Toshihiro Shimizu 890ddd
#include "toonz/rasterstrokegenerator.h"
manongjohn 75da26
#include "toonz/preferences.h"
Toshihiro Shimizu 890ddd
#include "tgl.h"
Toshihiro Shimizu 890ddd
#include "tenv.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tinbetween.h"
Toshihiro Shimizu 890ddd
#include "ttile.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/tpalettehandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheethandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshlevelhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tframehandle.h"
Toshihiro Shimizu 890ddd
#include "tools/toolhandle.h"
Toshihiro Shimizu 890ddd
#include "tools/toolutils.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// For Qt translation support
Toshihiro Shimizu 890ddd
#include <qcoreapplication></qcoreapplication>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tools/stylepicker.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/tselectionhandle.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/styleselection.h"
Toshihiro Shimizu 890ddd
#include "historytypes.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace ToolUtils;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TEnv::IntVar FingerInvert("InknpaintFingerInvert", 0);
Toshihiro Shimizu 890ddd
TEnv::DoubleVar FingerSize("InknpaintFingerSize", 10);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const int BackgroundStyle = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class FingerUndo final : public TRasterUndo {
Shinya Kitaoka 120a6e
  std::vector<tthickpoint> m_points;</tthickpoint>
Shinya Kitaoka 120a6e
  int m_styleId;
Shinya Kitaoka 120a6e
  bool m_invert;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  FingerUndo(TTileSetCM32 *tileSet, const std::vector<tthickpoint> &points,</tthickpoint>
Shinya Kitaoka 120a6e
             int styleId, bool invert, TXshSimpleLevel *level,
Shinya Kitaoka 120a6e
             const TFrameId &frameId)
Shinya Kitaoka 120a6e
      : TRasterUndo(tileSet, level, frameId, false, false, 0)
Shinya Kitaoka 120a6e
      , m_points(points)
Shinya Kitaoka 120a6e
      , m_styleId(styleId)
Shinya Kitaoka 120a6e
      , m_invert(invert) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void redo() const override {
Shinya Kitaoka 120a6e
    TToonzImageP image = m_level->getFrame(m_frameId, true);
Shinya Kitaoka 120a6e
    TRasterCM32P ras   = image->getRaster();
Shinya Kitaoka 120a6e
    RasterStrokeGenerator m_rasterTrack(ras, FINGER, INK, m_styleId,
Shinya Kitaoka 120a6e
                                        m_points[0], m_invert, 0, false);
Shinya Kitaoka 120a6e
    m_rasterTrack.setPointsSequence(m_points);
Shinya Kitaoka 120a6e
    m_rasterTrack.generateStroke(true);
Shinya Kitaoka 120a6e
    image->setSavebox(image->getSavebox() +
Shinya Kitaoka 120a6e
                      m_rasterTrack.getBBox(m_rasterTrack.getPointsSequence()));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ToolUtils::updateSaveBox();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
    notifyImageChanged();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  int getSize() const override {
Shinya Kitaoka 38fd86
    return sizeof(*this) + TRasterUndo::getSize();
Shinya Kitaoka 38fd86
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  QString getToolName() override { return QString("Finger Tool"); }
Shinya Kitaoka 473e70
  int getHistoryType() override { return HistoryType::FingerTool; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void drawLine(const TPointD &point, const TPointD ¢re, bool horizontal,
Shinya Kitaoka 120a6e
              bool isDecimal) {
Shinya Kitaoka 120a6e
  if (!isDecimal) {
Shinya Kitaoka 120a6e
    if (horizontal) {
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 1.5, point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y - 0.5, -point.x + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y - 0.5, -point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, -point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x - 0.5, -point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y - 0.5, point.x + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y - 0.5, point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 0.5, -point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 1.5, -point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, -point.x + 1.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x - 0.5, point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x + 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 1.5, point.y + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 1.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 1.5, point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y + 0.5, -point.x + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y - 0.5, -point.x + 1.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y - 0.5, -point.x + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y - 0.5, -point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, -point.y - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x + 0.5, -point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, -point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x - 0.5, -point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 1.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y + 0.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y - 0.5, point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y - 0.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y - 0.5, point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 1.5, -point.y - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 1.5, -point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 1.5, -point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 0.5, -point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 1.5, -point.x + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, -point.x + 1.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, -point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, point.y + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x + 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x - 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    if (horizontal) {
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 0.5, point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x + 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y + 0.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y + 0.5, point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y + 0.5, -point.x + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y + 0.5, -point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x + 0.5, -point.y - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 0.5, -point.y - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x - 0.5, -point.y - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x + 0.5, -point.y - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, -point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x - 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 0.5, point.y + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 0.5, point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x + 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y + 1.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y + 0.5, point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y + 0.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y + 0.5, point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y + 1.5, -point.x + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y + 0.5, -point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y + 0.5, -point.x + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y + 0.5, -point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 0.5, -point.y - 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 0.5, -point.y - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 0.5, -point.y - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x + 0.5, -point.y - 0.5) + centre);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, -point.y - 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x + 0.5, -point.y - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, -point.y - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x - 0.5, -point.y - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 1.5, -point.x + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, -point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, -point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 1.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, point.y + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x + 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x - 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void drawEmptyCircle(int thick, const TPointD &mousePos, bool isPencil,
Shinya Kitaoka 120a6e
                     bool isLxEven, bool isLyEven) {
Shinya Kitaoka 120a6e
  TPointD pos = mousePos;
Shinya Kitaoka 120a6e
  if (isLxEven) pos.x += 0.5;
Shinya Kitaoka 120a6e
  if (isLyEven) pos.y += 0.5;
Shinya Kitaoka 120a6e
  if (!isPencil)
Shinya Kitaoka 120a6e
    tglDrawCircle(pos, (thick + 1) * 0.5);
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    int x = 0, y = tround((thick * 0.5) - 0.5);
Shinya Kitaoka 120a6e
    int d           = 3 - 2 * (int)(thick * 0.5);
Shinya Kitaoka 120a6e
    bool horizontal = true, isDecimal = thick % 2 != 0;
Shinya Kitaoka 120a6e
    drawLine(TPointD(x, y), pos, horizontal, isDecimal);
Shinya Kitaoka 120a6e
    while (y > x) {
Shinya Kitaoka 120a6e
      if (d < 0) {
Shinya Kitaoka 120a6e
        d          = d + 4 * x + 6;
Shinya Kitaoka 120a6e
        horizontal = true;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        d          = d + 4 * (x - y) + 10;
Shinya Kitaoka 120a6e
        horizontal = false;
Shinya Kitaoka 120a6e
        y--;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      x++;
Shinya Kitaoka 120a6e
      drawLine(TPointD(x, y), pos, horizontal, isDecimal);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class FingerTool final : public TTool {
Shinya Kitaoka 120a6e
  Q_DECLARE_TR_FUNCTIONS(FingerTool)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  RasterStrokeGenerator *m_rasterTrack;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool m_firstTime;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double m_pointSize, m_distance2;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool m_selecting;
Shinya Kitaoka 120a6e
  TTileSaverCM32 *m_tileSaver;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPointD m_mousePos;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TIntProperty m_toolSize;
Shinya Kitaoka 120a6e
  TBoolProperty m_invert;
Shinya Kitaoka 120a6e
  TPropertyGroup m_prop;
Shinya Kitaoka 120a6e
  int m_cursor;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*---	作業中のFrameIdをクリック時に保存し、マウスリリース時(Undoの登録時)
Shinya Kitaoka 120a6e
                  に別のフレームに移動している場合があるため ---*/
Shinya Kitaoka 120a6e
  TFrameId m_workingFrameId;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*-- 最初のクリックでStyleを切り替える --*/
Shinya Kitaoka 120a6e
  void pick(const TPointD &pos);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  FingerTool();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void draw() override;
Shinya Kitaoka 120a6e
  void update(TToonzImageP ti, TRectD area);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void updateTranslation() override;
Shinya Kitaoka 473e70
Shinya Kitaoka 473e70
  void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override;
Shinya Kitaoka 473e70
  void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override;
Shinya Kitaoka 473e70
  void leftButtonUp(const TPointD &pos, const TMouseEvent &) override;
Shinya Kitaoka 473e70
  void mouseMove(const TPointD &pos, const TMouseEvent &e) override;
Shinya Kitaoka 473e70
  void onEnter() override;
Shinya Kitaoka 473e70
  void onLeave() override;
Shinya Kitaoka 473e70
  void onActivate() override;
Shinya Kitaoka 473e70
  void onDeactivate() override;
Shinya Kitaoka 473e70
  bool onPropertyChanged(std::string propertyName) override;
Shinya Kitaoka 473e70
Shinya Kitaoka 473e70
  TPropertyGroup *getProperties(int targetType) override { return &m_prop; }
Shinya Kitaoka 473e70
  ToolType getToolType() const override { return TTool::LevelWriteTool; }
Shinya Kitaoka 473e70
  int getCursorId() const override { return m_cursor; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int getColorClass() const { return 2; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*--
Shinya Kitaoka 120a6e
   * ドラッグ中にツールが切り替わった場合に備え、onDeactivateにもMouseReleaseと同じ処理を行う
Shinya Kitaoka 120a6e
   * --*/
Shinya Kitaoka 120a6e
  void finishBrush();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FingerTool fingerTool;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//  InkPaintTool implemention
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FingerTool::FingerTool()
Shinya Kitaoka 120a6e
    : TTool("T_Finger")
Shinya Kitaoka 120a6e
    , m_rasterTrack(0)
Shinya Kitaoka 120a6e
    , m_pointSize(-1)
Shinya Kitaoka 120a6e
    , m_selecting(false)
Shinya Kitaoka 120a6e
    , m_tileSaver(0)
Shinya Kitaoka 120a6e
    , m_cursor(ToolCursor::EraserCursor)
Shinya Kitaoka 120a6e
    , m_toolSize("Size:", 1, 100, 10, false)
Shinya Kitaoka 120a6e
    , m_invert("Invert", false)
Shinya Kitaoka 120a6e
    , m_firstTime(true)
Shinya Kitaoka 120a6e
    , m_workingFrameId(TFrameId()) {
Shinya Kitaoka 120a6e
  bind(TTool::ToonzImage);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_prop.bind(m_toolSize);
Shinya Kitaoka 120a6e
  m_prop.bind(m_invert);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_invert.setId("Invert");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void FingerTool::updateTranslation() {
Shinya Kitaoka 120a6e
  m_toolSize.setQStringName(tr("Size:"));
Shinya Kitaoka 120a6e
  m_invert.setQStringName(tr("Invert", NULL));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void FingerTool::draw() {
Shinya Kitaoka 120a6e
  if (m_pointSize == -1) {
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
manongjohn 75da26
  // If toggled off, don't draw brush outline
manongjohn 75da26
  if (!Preferences::instance()->isCursorOutlineEnabled()) return;
manongjohn 75da26
Shinya Kitaoka 120a6e
  TToonzImageP ti = (TToonzImageP)getImage(false);
Shinya Kitaoka 120a6e
  if (!ti) return;
Shinya Kitaoka 120a6e
  TRasterP ras = ti->getRaster();
Shinya Kitaoka 120a6e
  int lx       = ras->getLx();
Shinya Kitaoka 120a6e
  int ly       = ras->getLy();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if ((ToonzCheck::instance()->getChecks() & ToonzCheck::eInk) ||
Shinya Kitaoka 120a6e
      (ToonzCheck::instance()->getChecks() & ToonzCheck::ePaint))
Shinya Kitaoka 120a6e
    glColor3d(0.5, 0.8, 0.8);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    glColor3d(1.0, 0.0, 0.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  drawEmptyCircle(m_toolSize.getValue(), m_mousePos, true, lx % 2 == 0,
Shinya Kitaoka 120a6e
                  ly % 2 == 0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const UINT pointCount = 20;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool FingerTool::onPropertyChanged(std::string propertyName) {
Shinya Kitaoka 120a6e
  /*-- サイズ --*/
Shinya Kitaoka 120a6e
  if (propertyName == m_toolSize.getName()) {
Shinya Kitaoka 120a6e
    FingerSize = m_toolSize.getValue();
Shinya Kitaoka 120a6e
    double x   = m_toolSize.getValue();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    double minRange = 1;
Shinya Kitaoka 120a6e
    double maxRange = 100;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    double minSize = 0.01;
Shinya Kitaoka 120a6e
    double maxSize = 100;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_pointSize =
Shinya Kitaoka 120a6e
        (x - minRange) / (maxRange - minRange) * (maxSize - minSize) + minSize;
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Invert
Shinya Kitaoka 120a6e
  else if (propertyName == m_invert.getName()) {
Shinya Kitaoka 120a6e
    FingerInvert = (int)(m_invert.getValue());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void FingerTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  pick(pos);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_selecting = true;
Shinya Kitaoka 120a6e
  TImageP image(getImage(true));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (TToonzImageP ti = image) {
Shinya Kitaoka 120a6e
    TRasterCM32P ras = ti->getRaster();
Shinya Kitaoka 120a6e
    if (ras) {
Shinya Kitaoka 120a6e
      int thickness = m_toolSize.getValue();
Shinya Kitaoka 120a6e
      int styleId   = TTool::getApplication()->getCurrentLevelStyleIndex();
Shinya Kitaoka 120a6e
      TTileSetCM32 *tileSet = new TTileSetCM32(ras->getSize());
Shinya Kitaoka 120a6e
      m_tileSaver           = new TTileSaverCM32(ras, tileSet);
Shinya Kitaoka 120a6e
      m_rasterTrack         = new RasterStrokeGenerator(
Shinya Kitaoka 120a6e
          ras, FINGER, INK, styleId,
Shinya Kitaoka 120a6e
          TThickPoint(pos + convert(ras->getCenter()), thickness),
Shinya Kitaoka 120a6e
          m_invert.getValue(), 0, false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*-- 作業中Fidを現在のFIDにする --*/
Shinya Kitaoka 120a6e
      m_workingFrameId = getFrameId();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      m_tileSaver->save(m_rasterTrack->getLastRect());
Shinya Kitaoka 120a6e
      TRect modifiedBbox = m_rasterTrack->generateLastPieceOfStroke(true);
Shinya Kitaoka 120a6e
      invalidate();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void FingerTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  if (!m_selecting) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_mousePos = pos;
Shinya Kitaoka 120a6e
  if (TToonzImageP ri = TImageP(getImage(true))) {
Shinya Kitaoka 120a6e
    /*---	マウスを動かしながらショートカットで切り替わった場合、
Shinya Kitaoka 120a6e
                    いきなりleftButtonDragから呼ばれることがあり、
Shinya Kitaoka 120a6e
                    m_rasterTrackが無くて落ちることがある。 ---*/
Shinya Kitaoka 120a6e
    if (m_rasterTrack) {
Shinya Kitaoka 120a6e
      int thickness = m_toolSize.getValue();
Shinya Kitaoka 120a6e
      bool isAdded  = m_rasterTrack->add(
Shinya Kitaoka 120a6e
          TThickPoint(pos + convert(ri->getRaster()->getCenter()), thickness));
Shinya Kitaoka 120a6e
      if (isAdded) {
Shinya Kitaoka 120a6e
        m_tileSaver->save(m_rasterTrack->getLastRect());
Shinya Kitaoka 120a6e
        TRect modifiedBbox = m_rasterTrack->generateLastPieceOfStroke(true);
Shinya Kitaoka 120a6e
        invalidate();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void FingerTool::leftButtonUp(const TPointD &pos, const TMouseEvent &) {
Shinya Kitaoka 120a6e
  if (!m_selecting) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_mousePos = pos;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  finishBrush();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void FingerTool::mouseMove(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_mousePos = pos;
Shinya Kitaoka 120a6e
  TPointD pp(tround(pos.x), tround(pos.y));
Shinya Kitaoka 120a6e
  m_mousePos = pp;
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void FingerTool::onEnter() {
Shinya Kitaoka 120a6e
  if (m_firstTime) {
Shinya Kitaoka 120a6e
    m_invert.setValue(FingerInvert ? 1 : 0);
Shinya Kitaoka 120a6e
    m_toolSize.setValue(FingerSize);
Shinya Kitaoka 120a6e
    m_firstTime = false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  double x = m_toolSize.getValue();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double minRange = 1;
Shinya Kitaoka 120a6e
  double maxRange = 100;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double minSize = 0.01;
Shinya Kitaoka 120a6e
  double maxSize = 100;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_pointSize =
Shinya Kitaoka 120a6e
      (x - minRange) / (maxRange - minRange) * (maxSize - minSize) + minSize;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if ((TToonzImageP)getImage(false))
Shinya Kitaoka 120a6e
    m_cursor = ToolCursor::PenCursor;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    m_cursor = ToolCursor::CURSOR_NO;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void FingerTool::onLeave() { m_pointSize = -1; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void FingerTool::onActivate() { onEnter(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void FingerTool::onDeactivate() {
Shinya Kitaoka 120a6e
  /*---
Shinya Kitaoka 120a6e
   * マウスドラッグ中(m_selecting=true)にツールが切り替わったときに線を終わらせる
Shinya Kitaoka 120a6e
   * ---*/
Shinya Kitaoka 120a6e
  if (m_selecting) finishBrush();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
/*!
Shinya Kitaoka 120a6e
 * ドラッグ中にツールが切り替わった場合に備え、onDeactivateにもMouseReleaseと同じ処理を行う
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
void FingerTool::finishBrush() {
Shinya Kitaoka 120a6e
  if (TToonzImageP ti = (TToonzImageP)getImage(true)) {
Shinya Kitaoka 120a6e
    if (m_rasterTrack) {
Shinya Kitaoka 120a6e
      int thickness = m_toolSize.getValue();
Shinya Kitaoka 120a6e
      bool isAdded  = m_rasterTrack->add(TThickPoint(
Shinya Kitaoka 120a6e
          m_mousePos + convert(ti->getRaster()->getCenter()), thickness));
Shinya Kitaoka 120a6e
      if (isAdded) {
Shinya Kitaoka 120a6e
        m_tileSaver->save(m_rasterTrack->getLastRect());
Shinya Kitaoka 120a6e
        TRect modifiedBbox =
Shinya Kitaoka 120a6e
            m_rasterTrack->generateLastPieceOfStroke(true, true);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TTool::Application *app   = TTool::getApplication();
Shinya Kitaoka 120a6e
      TXshLevel *level          = app->getCurrentLevel()->getLevel();
Shinya Kitaoka 120a6e
      TXshSimpleLevelP simLevel = level->getSimpleLevel();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TFrameId frameId =
Shinya Kitaoka 120a6e
          m_workingFrameId.isEmptyFrame() ? getCurrentFid() : m_workingFrameId;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TUndoManager::manager()->add(new FingerUndo(
Shinya Kitaoka 120a6e
          m_tileSaver->getTileSet(), m_rasterTrack->getPointsSequence(),
Shinya Kitaoka 120a6e
          m_rasterTrack->getStyleId(), m_rasterTrack->isSelective(),
Shinya Kitaoka 120a6e
          simLevel.getPointer(), frameId));
Shinya Kitaoka 120a6e
      ToolUtils::updateSaveBox();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*! FIdを指定して、作業中にフレームが動いても、
Shinya Kitaoka 120a6e
              クリック時のFidのサムネイルが更新されるようにする。
Shinya Kitaoka 120a6e
      */
Shinya Kitaoka 120a6e
      notifyImageChanged(frameId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      invalidate();
Shinya Kitaoka 120a6e
      delete m_rasterTrack;
Shinya Kitaoka 120a6e
      m_rasterTrack = 0;
Shinya Kitaoka 120a6e
      delete m_tileSaver;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*-- 作業中fIdをリセット --*/
Shinya Kitaoka 120a6e
      m_workingFrameId = TFrameId();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  m_selecting = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void FingerTool::pick(const TPointD &pos) {
Shinya Kitaoka 120a6e
  int modeValue = 2;  // LINES
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TImageP image    = getImage(false);
Shinya Kitaoka 120a6e
  TToonzImageP ti  = image;
Shinya Kitaoka 120a6e
  TVectorImageP vi = image;
Shinya Kitaoka 120a6e
  TXshSimpleLevel *level =
Shinya Kitaoka 120a6e
      getApplication()->getCurrentLevel()->getSimpleLevel();
Shinya Kitaoka 120a6e
  if (!ti || !level) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*--- 画面外をpickしても拾えないようにする ---*/
Shinya Kitaoka 120a6e
  if (!m_viewer->getGeometry().contains(pos)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int subsampling = level->getImageSubsampling(getCurrentFid());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  StylePicker picker(image);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int styleId =
Shinya Kitaoka 120a6e
      picker.pickStyleId(TScale(1.0 / subsampling) * pos + TPointD(-0.5, -0.5),
Shinya Kitaoka 120a6e
                         getPixelSize() * getPixelSize(), modeValue);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (styleId < 0) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (modeValue == 2)  // LINES
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    /*--- pickLineモードのとき、取得Styleが0の場合はカレントStyleを変えない。
Shinya Kitaoka 120a6e
     * ---*/
Shinya Kitaoka 120a6e
    if (styleId == 0) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /*---
Shinya Kitaoka 120a6e
     * pickLineモードのとき、PurePaintの部分をクリックしてもカレントStyleを変えない
Shinya Kitaoka 120a6e
     * ---*/
Shinya Kitaoka 120a6e
    if (ti &&
Shinya Kitaoka 120a6e
        picker.pickTone(TScale(1.0 / subsampling) * pos +
Shinya Kitaoka 120a6e
                        TPointD(-0.5, -0.5)) == 255)
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*--- Styleを選択している場合は選択を解除する ---*/
Shinya Kitaoka 120a6e
  TSelection *selection =
Shinya Kitaoka 120a6e
      TTool::getApplication()->getCurrentSelection()->getSelection();
Shinya Kitaoka 120a6e
  if (selection) {
Shinya Kitaoka 120a6e
    TStyleSelection *styleSelection =
Shinya Kitaoka 120a6e
        dynamic_cast<tstyleselection *="">(selection);</tstyleselection>
Shinya Kitaoka 120a6e
    if (styleSelection) styleSelection->selectNone();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  getApplication()->setCurrentLevelStyleIndex(styleId);
Toshihiro Shimizu 890ddd
}