Toshihiro Shimizu 890ddd
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"
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
using namespace ToolUtils;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define LINES L"Lines"
Toshihiro Shimizu 890ddd
#define AREAS L"Areas"
Toshihiro Shimizu 890ddd
#define ALL L"Lines & Areas"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define NORMALERASE L"Normal"
Toshihiro Shimizu 890ddd
#define RECTERASE L"Rectangular"
Toshihiro Shimizu 890ddd
#define FREEHANDERASE L"Freehand"
Toshihiro Shimizu 890ddd
#define POLYLINEERASE L"Polyline"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TEnv::StringVar PaintBrushColorType("InknpaintPaintBrushColorType", "Areas");
Toshihiro Shimizu 890ddd
TEnv::IntVar PaintBrushSelective("InknpaintPaintBrushSelective", 0);
Toshihiro Shimizu 890ddd
TEnv::DoubleVar PaintBrushSize("InknpaintPaintBrushSize", 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 BrushUndo final : public TRasterUndo {
Shinya Kitaoka 120a6e
  std::vector<tthickpoint> m_points;</tthickpoint>
Shinya Kitaoka 120a6e
  int m_styleId;
Shinya Kitaoka 120a6e
  bool m_selective;
Shinya Kitaoka 120a6e
  ColorType m_colorType;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  BrushUndo(TTileSetCM32 *tileSet, const std::vector<tthickpoint> &points,</tthickpoint>
Shinya Kitaoka 120a6e
            ColorType colorType, int styleId, bool selective,
Shinya Kitaoka 120a6e
            TXshSimpleLevel *level, 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_selective(selective)
Shinya Kitaoka 120a6e
      , m_colorType(colorType) {}
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, PAINTBRUSH, m_colorType, m_styleId,
Shinya Kitaoka 120a6e
                                        m_points[0], m_selective, 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
    ToolUtils::updateSaveBox();
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 473e70
Shinya Kitaoka 473e70
  QString getToolName() override { return QString("Paint Brush Tool"); }
Shinya Kitaoka 473e70
  int getHistoryType() override { return HistoryType::PaintBrushTool; }
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 PaintBrushTool final : public TTool {
Shinya Kitaoka 120a6e
  Q_DECLARE_TR_FUNCTIONS(PaintBrushTool)
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_onlyEmptyAreas;
Shinya Kitaoka 120a6e
  TEnumProperty m_colorType;
Shinya Kitaoka 120a6e
  TPropertyGroup m_prop;
Shinya Kitaoka 120a6e
  int m_cursor;
Shinya Kitaoka 120a6e
  ColorType m_colorTypeBrush;
Shinya Kitaoka 120a6e
  /*--
Shinya Kitaoka 120a6e
     描画開始時のFrameIdを保存し、マウスリリース時(Undoの登録時)に別のフレームに
Shinya Kitaoka 120a6e
          移動している場合に備える --*/
Shinya Kitaoka 120a6e
  TFrameId m_workingFrameId;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  PaintBrushTool();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  ToolType getToolType() const override { return TTool::LevelWriteTool; }
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;
Toshihiro Shimizu 890ddd
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;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  TPropertyGroup *getProperties(int targetType) override { return &m_prop; }
Toshihiro Shimizu 890ddd
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();
Shinya Kitaoka 120a6e
  /*--- Brush、PaintBrush、EraserToolがPencilModeのときにTrueを返す。
Shinya Kitaoka 120a6e
     PaintBrushはピクセルのStyleIndexを入れ替えるツールのため、
Shinya Kitaoka 120a6e
       アンチエイリアスは存在しない、いわば常にPencilMode ---*/
Shinya Kitaoka 473e70
  bool isPencilModeActive() override { return true; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PaintBrushTool paintBrushTool;
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
PaintBrushTool::PaintBrushTool()
Shinya Kitaoka 120a6e
    : TTool("T_PaintBrush")
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
    // sostituire i nomi con quelli del current, tipo W_ToolOptions...
Shinya Kitaoka 120a6e
    , m_toolSize("Size:", 1, 100, 10, false)  // W_ToolOptions_BrushToolSize
Shinya Kitaoka 120a6e
    , m_colorType("Mode:")                    // W_ToolOptions_InkOrPaint
Shinya Kitaoka 120a6e
    , m_onlyEmptyAreas("Selective", false)    // W_ToolOptions_Selective
Shinya Kitaoka 120a6e
    , m_firstTime(true)
Shinya Kitaoka 120a6e
    , m_workingFrameId(TFrameId()) {
Shinya Kitaoka 120a6e
  m_colorType.addValue(LINES);
Shinya Kitaoka 120a6e
  m_colorType.addValue(AREAS);
Shinya Kitaoka 120a6e
  m_colorType.addValue(ALL);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bind(TTool::ToonzImage);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_prop.bind(m_toolSize);
Shinya Kitaoka 120a6e
  m_prop.bind(m_colorType);
Shinya Kitaoka 120a6e
  m_prop.bind(m_onlyEmptyAreas);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_onlyEmptyAreas.setId("Selective");
Shinya Kitaoka 120a6e
  m_colorType.setId("Mode");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PaintBrushTool::updateTranslation() {
Shinya Kitaoka 120a6e
  m_toolSize.setQStringName(tr("Size:"));
Shinya Kitaoka 120a6e
  m_colorType.setQStringName(tr("Mode:"));
Shinya Kitaoka 120a6e
  m_onlyEmptyAreas.setQStringName(tr("Selective", NULL));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PaintBrushTool::draw() {
Shinya Kitaoka 120a6e
  /*-- MouseLeave時にBrushTipが描かれるのを防止する --*/
Shinya Kitaoka 120a6e
  if (m_pointSize == -1) return;
Shinya Kitaoka 120a6e
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
      (ToonzCheck::instance()->getChecks() & ToonzCheck::eInk1))
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 PaintBrushTool::onPropertyChanged(std::string propertyName) {
Shinya Kitaoka 120a6e
  /*-- Size ---*/
Shinya Kitaoka 120a6e
  if (propertyName == m_toolSize.getName()) {
Shinya Kitaoka 120a6e
    PaintBrushSize = m_toolSize.getValue();
Shinya Kitaoka 120a6e
    double x       = m_toolSize.getValue();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    double minRange = 1;
Shinya Kitaoka 120a6e
    double maxRange = 100;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    double minSize = 0.01;
Shinya Kitaoka 120a6e
    double maxSize = 100;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_pointSize =
Shinya Kitaoka 120a6e
        (x - minRange) / (maxRange - minRange) * (maxSize - minSize) + minSize;
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Selective
Shinya Kitaoka 120a6e
  else if (propertyName == m_onlyEmptyAreas.getName()) {
Shinya Kitaoka 120a6e
    if (m_onlyEmptyAreas.getValue() && m_colorType.getValue() == LINES) {
Shinya Kitaoka 120a6e
      m_colorType.setValue(AREAS);
Shinya Kitaoka 120a6e
      PaintBrushColorType = ::to_string(m_colorType.getValue());
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    PaintBrushSelective = (int)(m_onlyEmptyAreas.getValue());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Areas, Lines etc.
Shinya Kitaoka 120a6e
  else if (propertyName == m_colorType.getName()) {
Shinya Kitaoka 120a6e
    if (m_colorType.getValue() == LINES) {
Shinya Kitaoka 120a6e
      PaintBrushSelective = (int)(m_onlyEmptyAreas.getValue());
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    PaintBrushColorType = ::to_string(m_colorType.getValue());
Shinya Kitaoka 120a6e
    /*--- ColorModelのCursor更新のためにSIGNALを出す ---*/
Shinya Kitaoka 120a6e
    TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PaintBrushTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_selecting = true;
Shinya Kitaoka 120a6e
  TImageP image(getImage(true));
Shinya Kitaoka 120a6e
  if (m_colorType.getValue() == LINES) m_colorTypeBrush = INK;
Shinya Kitaoka 120a6e
  if (m_colorType.getValue() == AREAS) m_colorTypeBrush = PAINT;
Shinya Kitaoka 120a6e
  if (m_colorType.getValue() == ALL) m_colorTypeBrush   = INKNPAINT;
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, PAINTBRUSH, m_colorTypeBrush, styleId,
Shinya Kitaoka 120a6e
          TThickPoint(pos + convert(ras->getCenter()), thickness),
Shinya Kitaoka 120a6e
          m_onlyEmptyAreas.getValue(), 0, false);
Shinya Kitaoka 120a6e
      /*-- 現在のFidを記憶 --*/
Shinya Kitaoka 120a6e
      m_workingFrameId = getFrameId();
Shinya Kitaoka 120a6e
      m_tileSaver->save(m_rasterTrack->getLastRect());
Shinya Kitaoka 120a6e
      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 PaintBrushTool::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から呼ばれることがあり、m_rasterTrackが無い可能性がある
Shinya Kitaoka 120a6e
 ---*/
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 PaintBrushTool::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 PaintBrushTool::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 PaintBrushTool::onEnter() {
Shinya Kitaoka 120a6e
  if (m_firstTime) {
Shinya Kitaoka 120a6e
    m_onlyEmptyAreas.setValue(PaintBrushSelective ? 1 : 0);
Shinya Kitaoka 120a6e
    m_colorType.setValue(::to_wstring(PaintBrushColorType.getValue()));
Shinya Kitaoka 120a6e
    m_toolSize.setValue(PaintBrushSize);
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 PaintBrushTool::onLeave() { m_pointSize = -1; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PaintBrushTool::onActivate() { onEnter(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PaintBrushTool::onDeactivate() {
Shinya Kitaoka 120a6e
  /*--マウスドラッグ中(m_selecting=true)にツールが切り替わったときに描画の終了処理を行う---*/
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 PaintBrushTool::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
        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
      /*-- 描画中にフレームが動いても、描画開始時のFidに対してUndoを記録する
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 BrushUndo(
Shinya Kitaoka 120a6e
          m_tileSaver->getTileSet(), m_rasterTrack->getPointsSequence(),
Shinya Kitaoka 120a6e
          m_colorTypeBrush, m_rasterTrack->getStyleId(),
Shinya Kitaoka 120a6e
          m_rasterTrack->isSelective(), simLevel.getPointer(), frameId));
Shinya Kitaoka 120a6e
      ToolUtils::updateSaveBox();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*--- FIdを指定して、描画中にフレームが変わっても、
Shinya Kitaoka 120a6e
              クリック時のFidのサムネイルが更新されるようにする。---*/
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
      /*--- 作業中のフレームをリセット ---*/
Shinya Kitaoka 120a6e
      m_workingFrameId = TFrameId();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ToolUtils::updateSaveBox();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_selecting = false;
Toshihiro Shimizu 890ddd
}