Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/tpalettehandle.h"
Toshihiro Shimizu 890ddd
#include "tools/toolhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tobjecthandle.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/tool.h"
Toshihiro Shimizu 890ddd
#include "tcolorstyles.h"
Toshihiro Shimizu 890ddd
#include "tpalette.h"
Toshihiro Shimizu 890ddd
#include "tools/toolutils.h"
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
#include "tmathutil.h"
Toshihiro Shimizu 890ddd
#include "tools/cursors.h"
Toshihiro Shimizu 890ddd
#include "tproperty.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
#include "drawutil.h"
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
#include "tenv.h"
Toshihiro Shimizu 890ddd
#include "bluredbrush.h"
Toshihiro Shimizu 890ddd
#include "toonz/ttileset.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzimageutils.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobject.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobjectspline.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/imageutils.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/dvdialog.h"
Toshihiro Shimizu 890ddd
#include "toonz/trasterimageutils.h"
Toshihiro Shimizu 890ddd
#include "toonz/preferences.h"
Toshihiro Shimizu 890ddd
#include "tw/keycodes.h"
Toshihiro Shimizu 890ddd
#include "historytypes.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
class GeometricTool;
Toshihiro Shimizu 890ddd
class MultiLinePrimitive;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TEnv::DoubleVar GeometricSize("InknpaintGeometricSize", 1);
Toshihiro Shimizu 890ddd
TEnv::DoubleVar GeometricRasterSize("InknpaintGeometricRasterSize", 1);
Toshihiro Shimizu 890ddd
TEnv::StringVar GeometricType("InknpaintGeometricType", "Rectangle");
Toshihiro Shimizu 890ddd
TEnv::IntVar GeometricEdgeCount("InknpaintGeometricEdgeCount", 3);
Toshihiro Shimizu 890ddd
TEnv::IntVar GeometricSelective("InknpaintGeometricSelective", 0);
Toshihiro Shimizu 890ddd
TEnv::IntVar GeometricGroupIt("InknpaintGeometricGroupIt", 0);
Toshihiro Shimizu 890ddd
TEnv::IntVar GeometricAutofill("InknpaintGeometricAutofill", 0);
Toshihiro Shimizu 890ddd
TEnv::IntVar GeometricPencil("InknpaintGeometricPencil", 0);
Toshihiro Shimizu 890ddd
TEnv::DoubleVar GeometricBrushHardness("InknpaintGeometricHardness", 100);
Toshihiro Shimizu 890ddd
TEnv::DoubleVar GeometricOpacity("InknpaintGeometricOpacity", 100);
Toshihiro Shimizu 890ddd
TEnv::IntVar GeometricCapStyle("InknpaintGeometricCapStyle", 0);
Toshihiro Shimizu 890ddd
TEnv::IntVar GeometricJoinStyle("InknpaintGeometricJoinStyle", 0);
Toshihiro Shimizu 890ddd
TEnv::IntVar GeometricMiterValue("InknpaintGeometricMiterValue", 4);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define ROUNDC_WSTR L"round_cap"
Toshihiro Shimizu 890ddd
#define BUTT_WSTR L"butt_cap"
Toshihiro Shimizu 890ddd
#define PROJECTING_WSTR L"projecting_cap"
Toshihiro Shimizu 890ddd
#define ROUNDJ_WSTR L"round_join"
Toshihiro Shimizu 890ddd
#define BEVEL_WSTR L"bevel_join"
Toshihiro Shimizu 890ddd
#define MITER_WSTR L"miter_join"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Utility Functions
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPointD rectify(const TPointD &oldPos, const TPointD &pos) {
Shinya Kitaoka 120a6e
  const double h             = sqrt(2.0) / 2.0;
Shinya Kitaoka 120a6e
  const TPointD directions[] = {TPointD(1, 0),  TPointD(h, h),  TPointD(0, 1),
Shinya Kitaoka 120a6e
                                TPointD(-h, h), TPointD(-1, 0), TPointD(-h, -h),
Shinya Kitaoka 120a6e
                                TPointD(0, -1), TPointD(h, -h)};
Shinya Kitaoka 120a6e
  TPointD v        = pos - oldPos;
Shinya Kitaoka 120a6e
  int j            = 0;
Shinya Kitaoka 120a6e
  double bestValue = v * directions[j];
Shinya Kitaoka 120a6e
  for (int k = 1; k < 8; k++) {
Shinya Kitaoka 120a6e
    double value = v * directions[k];
Shinya Kitaoka 120a6e
    if (value > bestValue) {
Shinya Kitaoka 120a6e
      bestValue = value;
Shinya Kitaoka 120a6e
      j         = k;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return oldPos + bestValue * directions[j];
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPointD computeSpeed(TPointD p0, TPointD p1, double factor) {
Shinya Kitaoka 120a6e
  TPointD d = p1 - p0;
Shinya Kitaoka 120a6e
  return (d == TPointD()) ? TPointD() : d * (factor / norm(d));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TRect drawBluredBrush(const TRasterImageP &ri, TStroke *stroke, int thick,
Shinya Kitaoka 120a6e
                      double hardness, double opacity) {
Shinya Kitaoka 120a6e
  TStroke *s       = new TStroke(*stroke);
Shinya Kitaoka 120a6e
  TPointD riCenter = ri->getRaster()->getCenterD();
Shinya Kitaoka 120a6e
  s->transform(TTranslation(riCenter));
Shinya Kitaoka 120a6e
  int styleId    = s->getStyle();
Shinya Kitaoka 120a6e
  TPalette *plt  = ri->getPalette();
Shinya Kitaoka 120a6e
  TPixel32 color = plt->getStyle(styleId)->getMainColor();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD bbox      = s->getBBox();
Shinya Kitaoka 120a6e
  TRect bboxI      = convert(bbox).enlarge(1);
Shinya Kitaoka 120a6e
  TRect rectRender = bboxI * ri->getRaster()->getBounds();
Shinya Kitaoka 120a6e
  if (rectRender.isEmpty()) return TRect();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRaster32P workRas(ri->getRaster()->getSize());
Shinya Kitaoka 120a6e
  TRaster32P backupRas = ri->getRaster()->clone();
Shinya Kitaoka 120a6e
  workRas->clear();
Shinya Kitaoka 120a6e
  QRadialGradient brushPad = ToolUtils::getBrushPad(thick, hardness);
Shinya Kitaoka 120a6e
  BluredBrush brush(workRas, thick, brushPad, false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int i, chunkCount = s->getChunkCount();
Shinya Kitaoka 120a6e
  for (i = 0; i < chunkCount; i++) {
Shinya Kitaoka 120a6e
    const TThickQuadratic *q = s->getChunk(i);
Shinya Kitaoka 120a6e
    std::vector<tthickpoint> points;</tthickpoint>
Shinya Kitaoka 120a6e
    points.push_back(q->getThickP0());
Shinya Kitaoka 120a6e
    points.push_back(q->getThickP1());
Shinya Kitaoka 120a6e
    points.push_back(q->getThickP2());
Shinya Kitaoka 120a6e
    // i punti contenuti nello stroke sembra che haano la tickness pari al
Shinya Kitaoka 120a6e
    // raggio e non al diametro del punto!
Shinya Kitaoka 120a6e
    points[0].thick *= 2;
Shinya Kitaoka 120a6e
    points[1].thick *= 2;
Shinya Kitaoka 120a6e
    points[2].thick *= 2;
Shinya Kitaoka 120a6e
    TRect chunkBox = brush.getBoundFromPoints(points);
Shinya Kitaoka 120a6e
    brush.addArc(points[0], points[1], points[2], 1, 1);
Shinya Kitaoka 120a6e
    brush.updateDrawing(ri->getRaster(), backupRas, color, chunkBox, opacity);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  delete s;
Shinya Kitaoka 120a6e
  return rectRender;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TRect drawBluredBrush(const TToonzImageP &ti, TStroke *stroke, int thick,
Shinya Kitaoka 120a6e
                      double hardness, bool selective) {
Shinya Kitaoka 120a6e
  TStroke *s       = new TStroke(*stroke);
Shinya Kitaoka 120a6e
  TPointD riCenter = ti->getRaster()->getCenterD();
Shinya Kitaoka 120a6e
  s->transform(TTranslation(riCenter));
Shinya Kitaoka 120a6e
  int styleId = s->getStyle();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD bbox      = s->getBBox();
Shinya Kitaoka 120a6e
  TRect bboxI      = convert(bbox).enlarge(1);
Shinya Kitaoka 120a6e
  TRect rectRender = bboxI * ti->getRaster()->getBounds();
Shinya Kitaoka 120a6e
  if (rectRender.isEmpty()) return TRect();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRaster32P workRas(ti->getRaster()->getSize());
Shinya Kitaoka 120a6e
  TRasterCM32P backupRas = ti->getRaster()->clone();
Shinya Kitaoka 120a6e
  workRas->clear();
Shinya Kitaoka 120a6e
  QRadialGradient brushPad = ToolUtils::getBrushPad(thick, hardness);
Shinya Kitaoka 120a6e
  BluredBrush brush(workRas, thick, brushPad, false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int i, chunkCount = s->getChunkCount();
Shinya Kitaoka 120a6e
  for (i = 0; i < chunkCount; i++) {
Shinya Kitaoka 120a6e
    const TThickQuadratic *q = s->getChunk(i);
Shinya Kitaoka 120a6e
    std::vector<tthickpoint> points;</tthickpoint>
Shinya Kitaoka 120a6e
    points.push_back(q->getThickP0());
Shinya Kitaoka 120a6e
    points.push_back(q->getThickP1());
Shinya Kitaoka 120a6e
    points.push_back(q->getThickP2());
Shinya Kitaoka 120a6e
    // i punti contenuti nello stroke sembra che haano la tickness pari al
Shinya Kitaoka 120a6e
    // raggio e non al diametro del punto!
Shinya Kitaoka 120a6e
    points[0].thick *= 2;
Shinya Kitaoka 120a6e
    points[1].thick *= 2;
Shinya Kitaoka 120a6e
    points[2].thick *= 2;
Shinya Kitaoka 120a6e
    TRect chunkBox = brush.getBoundFromPoints(points);
Shinya Kitaoka 120a6e
    brush.addArc(points[0], points[1], points[2], 1, 1);
Shinya Kitaoka 120a6e
    brush.updateDrawing(ti->getRaster(), backupRas, chunkBox, styleId,
Shinya Kitaoka 120a6e
                        selective);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  delete s;
Shinya Kitaoka 120a6e
  return rectRender;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class MultilinePrimitiveUndo final : public TUndo {
Shinya Kitaoka 120a6e
  std::vector<tpointd> m_oldVertex;</tpointd>
Shinya Kitaoka 120a6e
  std::vector<tpointd> m_newVertex;</tpointd>
Shinya Kitaoka 120a6e
  MultiLinePrimitive *m_tool;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  MultilinePrimitiveUndo(const std::vector<tpointd> &vertex,</tpointd>
Shinya Kitaoka 120a6e
                         MultiLinePrimitive *tool)
Shinya Kitaoka 120a6e
      : TUndo(), m_oldVertex(vertex), m_tool(tool), m_newVertex() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~MultilinePrimitiveUndo() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void undo() const override;
Shinya Kitaoka 473e70
  void redo() const override;
Shinya Kitaoka 120a6e
  void setNewVertex(const std::vector<tpointd> &vertex) {</tpointd>
Shinya Kitaoka 120a6e
    m_newVertex = vertex;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  int getSize() const override { return sizeof(this); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  QString getToolName();
Shinya Kitaoka 473e70
  int getHistoryType() override { return HistoryType::GeometricTool; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class FullColorBluredPrimitiveUndo final : public UndoFullColorPencil {
Shinya Kitaoka 120a6e
  int m_thickness;
Shinya Kitaoka 120a6e
  double m_hardness;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  FullColorBluredPrimitiveUndo(TXshSimpleLevel *level, const TFrameId &frameId,
Shinya Kitaoka 120a6e
                               TStroke *stroke, int thickness, double hardness,
Shinya Kitaoka 120a6e
                               double opacity, bool doAntialias,
Shinya Kitaoka 120a6e
                               bool createdFrame, bool createdLevel)
Shinya Kitaoka 120a6e
      : UndoFullColorPencil(level, frameId, stroke, opacity, doAntialias,
Shinya Kitaoka 120a6e
                            createdFrame, createdLevel)
Shinya Kitaoka 120a6e
      , m_thickness(thickness)
Shinya Kitaoka 120a6e
      , m_hardness(hardness) {
Shinya Kitaoka 120a6e
    TRasterP raster = getImage()->getRaster();
Shinya Kitaoka 120a6e
    TDimension d    = raster->getSize();
Shinya Kitaoka 120a6e
    m_tiles         = new TTileSetFullColor(d);
Shinya Kitaoka 120a6e
    TRect rect      = convert(stroke->getBBox()) +
Shinya Kitaoka 120a6e
                 TPoint((int)(d.lx * 0.5), (int)(d.ly * 0.5));
Shinya Kitaoka 120a6e
    m_tiles->add(raster, rect.enlarge(2));
Shinya Kitaoka 120a6e
    m_stroke = new TStroke(*stroke);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~FullColorBluredPrimitiveUndo() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void redo() const override {
Shinya Kitaoka 120a6e
    insertLevelAndFrameIfNeeded();
Shinya Kitaoka 120a6e
    TRasterImageP ri = getImage();
Shinya Kitaoka 120a6e
    if (!ri) return;
Shinya Kitaoka 120a6e
    drawBluredBrush(ri, m_stroke, m_thickness, m_hardness, m_opacity);
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 UndoFullColorPencil::getSize() + sizeof(this);
Shinya Kitaoka 38fd86
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*-- Hardness<100 のときの GeometricToolのUndo --*/
Shinya Kitaoka d1f6c4
class CMBluredPrimitiveUndo final : public UndoRasterPencil {
Shinya Kitaoka 120a6e
  int m_thickness;
Shinya Kitaoka 120a6e
  double m_hardness;
Shinya Kitaoka 120a6e
  bool m_selective;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  CMBluredPrimitiveUndo(TXshSimpleLevel *level, const TFrameId &frameId,
Shinya Kitaoka 120a6e
                        TStroke *stroke, int thickness, double hardness,
Shinya Kitaoka 120a6e
                        bool selective, bool doAntialias, bool createdFrame,
Shinya Kitaoka 120a6e
                        bool createdLevel, std::string primitiveName)
Shinya Kitaoka 120a6e
      : UndoRasterPencil(level, frameId, stroke, selective, false, doAntialias,
Shinya Kitaoka 120a6e
                         createdFrame, createdLevel, primitiveName)
Shinya Kitaoka 120a6e
      , m_thickness(thickness)
Shinya Kitaoka 120a6e
      , m_hardness(hardness)
Shinya Kitaoka 120a6e
      , m_selective(selective) {
Shinya Kitaoka 120a6e
    TRasterCM32P raster = getImage()->getRaster();
Shinya Kitaoka 120a6e
    TDimension d        = raster->getSize();
Shinya Kitaoka 120a6e
    m_tiles             = new TTileSetCM32(d);
Shinya Kitaoka 120a6e
    TRect rect          = convert(stroke->getBBox()) +
Shinya Kitaoka 120a6e
                 TPoint((int)(d.lx * 0.5), (int)(d.ly * 0.5));
Shinya Kitaoka 120a6e
    m_tiles->add(raster, rect.enlarge(2));
Shinya Kitaoka 120a6e
    m_stroke = new TStroke(*stroke);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~CMBluredPrimitiveUndo() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void redo() const override {
Shinya Kitaoka 120a6e
    insertLevelAndFrameIfNeeded();
Shinya Kitaoka 120a6e
    TToonzImageP ti = getImage();
Shinya Kitaoka 120a6e
    if (!ti) return;
Shinya Kitaoka 120a6e
    drawBluredBrush(ti, m_stroke, m_thickness, m_hardness, m_selective);
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 UndoRasterPencil::getSize() + sizeof(this);
Shinya Kitaoka 38fd86
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class PrimitiveParam {
Shinya Kitaoka 120a6e
  Q_DECLARE_TR_FUNCTIONS(PrimitiveParam)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TDoubleProperty m_toolSize;
Shinya Kitaoka 120a6e
  TIntProperty m_rasterToolSize;
Shinya Kitaoka 120a6e
  TDoubleProperty m_opacity;
Shinya Kitaoka 120a6e
  TDoubleProperty m_hardness;
Shinya Kitaoka 120a6e
  TEnumProperty m_type;
Shinya Kitaoka 120a6e
  TIntProperty m_edgeCount;
Shinya Kitaoka 120a6e
  TBoolProperty m_autogroup;
Shinya Kitaoka 120a6e
  TBoolProperty m_autofill;
Shinya Kitaoka 120a6e
  TBoolProperty m_selective;
Shinya Kitaoka 120a6e
  TBoolProperty m_pencil;
Shinya Kitaoka 120a6e
  TEnumProperty m_capStyle;
Shinya Kitaoka 120a6e
  TEnumProperty m_joinStyle;
Shinya Kitaoka 120a6e
  TIntProperty m_miterJoinLimit;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPropertyGroup m_prop[2];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int m_targetType;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  PrimitiveParam(int targetType)
Shinya Kitaoka 120a6e
      : m_type("Shape:")  // "W_ToolOptions_ShapeType")
Shinya Kitaoka 120a6e
      , m_toolSize("Size:", 0, 100,
Shinya Kitaoka 120a6e
                   1)  // "W_ToolOptions_ShapeThickness", 0,30,1)
Shinya Kitaoka 120a6e
      , m_rasterToolSize("Size:", 1, 100, 1)
Shinya Kitaoka 120a6e
      , m_opacity("Opacity:", 0, 100, 100)
Shinya Kitaoka 120a6e
      , m_hardness("Hardness:", 0, 100, 100)
Shinya Kitaoka 120a6e
      , m_edgeCount("Polygon Sides:", 3, 15, 3)
Shinya Kitaoka 120a6e
      , m_autogroup("Auto Group", false)
Shinya Kitaoka 120a6e
      , m_autofill("Auto Fill", false)
Shinya Kitaoka 120a6e
      , m_selective("Selective", false)
Shinya Kitaoka 120a6e
      , m_pencil("Pencil Mode", false)
Shinya Kitaoka 120a6e
      , m_capStyle("Cap")
Shinya Kitaoka 120a6e
      , m_joinStyle("Join")
Shinya Kitaoka 120a6e
      , m_miterJoinLimit("Miter:", 0, 100, 4)
Shinya Kitaoka 120a6e
      , m_targetType(targetType) {
Shinya Kitaoka 120a6e
    if (targetType & TTool::Vectors) m_prop[0].bind(m_toolSize);
Shinya Kitaoka 120a6e
    if (targetType & TTool::ToonzImage || targetType & TTool::RasterImage) {
Shinya Kitaoka 120a6e
      m_prop[0].bind(m_rasterToolSize);
Shinya Kitaoka 120a6e
      m_prop[0].bind(m_hardness);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (targetType & TTool::RasterImage) m_prop[0].bind(m_opacity);
Shinya Kitaoka 120a6e
    m_prop[0].bind(m_type);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_prop[0].bind(m_edgeCount);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (targetType & TTool::Vectors) {
Shinya Kitaoka 120a6e
      m_prop[0].bind(m_autogroup);
Shinya Kitaoka 120a6e
      m_prop[0].bind(m_autofill);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (targetType & TTool::ToonzImage) {
Shinya Kitaoka 120a6e
      m_prop[0].bind(m_selective);
Shinya Kitaoka 120a6e
      m_prop[0].bind(m_pencil);
Shinya Kitaoka 120a6e
      m_pencil.setId("PencilMode");
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_capStyle.addValue(BUTT_WSTR);
Shinya Kitaoka 120a6e
    m_capStyle.addValue(ROUNDC_WSTR);
Shinya Kitaoka 120a6e
    m_capStyle.addValue(PROJECTING_WSTR);
Shinya Kitaoka 120a6e
    m_capStyle.setId("Cap");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_joinStyle.addValue(MITER_WSTR);
Shinya Kitaoka 120a6e
    m_joinStyle.addValue(ROUNDJ_WSTR);
Shinya Kitaoka 120a6e
    m_joinStyle.addValue(BEVEL_WSTR);
Shinya Kitaoka 120a6e
    m_joinStyle.setId("Join");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_miterJoinLimit.setId("Miter");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_prop[1].bind(m_capStyle);
Shinya Kitaoka 120a6e
    m_prop[1].bind(m_joinStyle);
Shinya Kitaoka 120a6e
    m_prop[1].bind(m_miterJoinLimit);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_selective.setId("Selective");
Shinya Kitaoka 120a6e
    m_autogroup.setId("AutoGroup");
Shinya Kitaoka 120a6e
    m_autofill.setId("Autofill");
Shinya Kitaoka 120a6e
    m_type.setId("GeometricShape");
Shinya Kitaoka 120a6e
    m_edgeCount.setId("GeometricEdge");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void updateTranslation() {
Shinya Kitaoka 120a6e
    m_type.setQStringName(tr("Shape:"));
Shinya Kitaoka 120a6e
    m_toolSize.setQStringName(tr("Size:"));
Shinya Kitaoka 120a6e
    m_rasterToolSize.setQStringName(tr("Thickness:"));
Shinya Kitaoka 120a6e
    m_opacity.setQStringName(tr("Opacity:"));
Shinya Kitaoka 120a6e
    m_hardness.setQStringName(tr("Hardness:"));
Shinya Kitaoka 120a6e
    m_edgeCount.setQStringName(tr("Polygon Sides:"));
Shinya Kitaoka 120a6e
    m_autogroup.setQStringName(tr("Auto Group"));
Shinya Kitaoka 120a6e
    m_autofill.setQStringName(tr("Auto Fill"));
Shinya Kitaoka 120a6e
    m_selective.setQStringName(tr("Selective"));
Shinya Kitaoka 120a6e
    m_pencil.setQStringName(tr("Pencil Mode"));
Shinya Kitaoka 120a6e
    m_capStyle.setQStringName(tr("Cap"));
Shinya Kitaoka 120a6e
    m_joinStyle.setQStringName(tr("Join"));
Shinya Kitaoka 120a6e
    m_miterJoinLimit.setQStringName(tr("Miter:"));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Abstract Class Primitive
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class Primitive {
Toshihiro Shimizu 890ddd
protected:
Shinya Kitaoka 120a6e
  bool m_isEditing, m_rasterTool, m_isPrompting;
Shinya Kitaoka 120a6e
  GeometricTool *m_tool;
Shinya Kitaoka 120a6e
  PrimitiveParam *m_param;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Primitive(PrimitiveParam *param, GeometricTool *tool, bool rasterTool)
Shinya Kitaoka 120a6e
      : m_param(param)
Shinya Kitaoka 120a6e
      , m_tool(tool)
Shinya Kitaoka 120a6e
      , m_isEditing(false)
Shinya Kitaoka 120a6e
      , m_rasterTool(rasterTool)
Shinya Kitaoka 120a6e
      , m_isPrompting(false) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double getThickness() const {
Shinya Kitaoka 120a6e
    if (m_rasterTool)
Shinya Kitaoka 120a6e
      return m_param->m_rasterToolSize.getValue() * 0.5;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      return m_param->m_toolSize.getValue() * 0.5;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void setIsPrompting(bool value) { m_isPrompting = value; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  virtual std::string getName() const = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  virtual ~Primitive() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  virtual void leftButtonDown(const TPointD &p, const TMouseEvent &e){};
Shinya Kitaoka 120a6e
  virtual void leftButtonDrag(const TPointD &p, const TMouseEvent &e){};
Shinya Kitaoka 120a6e
  virtual void leftButtonUp(const TPointD &p, const TMouseEvent &e){};
Shinya Kitaoka 120a6e
  virtual void leftButtonDoubleClick(const TPointD &, const TMouseEvent &e){};
Shinya Kitaoka 120a6e
  virtual void rightButtonDown(const TPointD &p, const TMouseEvent &e){};
Shinya Kitaoka 120a6e
  virtual void mouseMove(const TPointD &p, const TMouseEvent &e){};
Shinya Kitaoka 120a6e
  virtual bool keyDown(int key, const TPoint &point) { return false; }
Shinya Kitaoka 120a6e
  virtual void onEnter(){};
Shinya Kitaoka 120a6e
  virtual void draw(){};
Shinya Kitaoka 120a6e
  virtual void onActivate(){};
Shinya Kitaoka 120a6e
  virtual void onDeactivate(){};
Shinya Kitaoka 120a6e
  virtual void onImageChanged(){};
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  virtual TStroke *makeStroke() const = 0;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Rectangle Primitive Class Declaration
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class RectanglePrimitive final : public Primitive {
Shinya Kitaoka 120a6e
  TRectD m_selectingRect;
Shinya Kitaoka 120a6e
  TPointD m_pos;
Shinya Kitaoka 120a6e
  TPointD m_startPoint;
Shinya Kitaoka 120a6e
  TPixel32 m_color;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  RectanglePrimitive(PrimitiveParam *param, GeometricTool *tool,
Shinya Kitaoka 120a6e
                     bool reasterTool)
Shinya Kitaoka 120a6e
      : Primitive(param, tool, reasterTool) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  std::string getName() const override {
Shinya Kitaoka 120a6e
    return "Rectangle";
Shinya Kitaoka 120a6e
  }  // W_ToolOptions_ShapeRect"; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  TStroke *makeStroke() const override;
Shinya Kitaoka 473e70
  void draw() override;
Shinya Kitaoka 473e70
  void leftButtonDown(const TPointD &pos, const TMouseEvent &) override;
Shinya Kitaoka 473e70
  void leftButtonDrag(const TPointD &realPos, 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;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Circle Primitive Class Declaration
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class CirclePrimitive final : public Primitive {
Shinya Kitaoka 120a6e
  TPointD m_centre;
Shinya Kitaoka 120a6e
  TPointD m_pos;
Shinya Kitaoka 120a6e
  double m_radius;
Shinya Kitaoka 120a6e
  TPixel32 m_color;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  CirclePrimitive(PrimitiveParam *param, GeometricTool *tool, bool reasterTool)
Shinya Kitaoka 120a6e
      : Primitive(param, tool, reasterTool) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  std::string getName() const override {
Shinya Kitaoka 120a6e
    return "Circle";
Shinya Kitaoka 120a6e
  }  // W_ToolOptions_ShapeCircle";}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void draw() override;
Shinya Kitaoka 473e70
  void leftButtonDown(const TPointD &pos, const TMouseEvent &) override;
Shinya Kitaoka 473e70
  void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override;
Shinya Kitaoka 473e70
  TStroke *makeStroke() const 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;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// MultiLine Primitive Class Declaration
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const double joinDistance = 5.0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class MultiLinePrimitive : public Primitive {
Toshihiro Shimizu 890ddd
protected:
Shinya Kitaoka 120a6e
  std::vector<tpointd> m_vertex;</tpointd>
Shinya Kitaoka 120a6e
  TPointD m_mousePosition;
Shinya Kitaoka 120a6e
  TPixel32 m_color;
Shinya Kitaoka 120a6e
  bool m_closed, m_isSingleLine;
Shinya Kitaoka 120a6e
  bool m_speedMoved;        //!< True after moveSpeed(), false after addVertex()
Shinya Kitaoka 120a6e
  bool m_beforeSpeedMoved;  //!< Old value of m_speedMoved
Shinya Kitaoka 120a6e
  bool m_ctrlDown;          //!< Whether ctrl is hold down
Shinya Kitaoka 120a6e
  MultilinePrimitiveUndo *m_undo;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  MultiLinePrimitive(PrimitiveParam *param, GeometricTool *tool,
Shinya Kitaoka 120a6e
                     bool reasterTool)
Shinya Kitaoka 120a6e
      : Primitive(param, tool, reasterTool)
Shinya Kitaoka 120a6e
      , m_closed(false)
Shinya Kitaoka 120a6e
      , m_isSingleLine(false)
Shinya Kitaoka 120a6e
      , m_speedMoved(false)
Shinya Kitaoka 120a6e
      , m_beforeSpeedMoved(false)
Shinya Kitaoka 120a6e
      , m_ctrlDown(false) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  std::string getName() const override {
Shinya Kitaoka 120a6e
    return "Polyline";
Shinya Kitaoka 120a6e
  }  // W_ToolOptions_ShapePolyline";}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void addVertex(const TPointD &pos);
Shinya Kitaoka 120a6e
  void moveSpeed(const TPointD &delta);
Shinya Kitaoka 473e70
  void draw() override;
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 leftButtonDoubleClick(const TPointD &, 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
  bool keyDown(int key, const TPoint &point) override;
Shinya Kitaoka 473e70
  TStroke *makeStroke() const override;
Shinya Kitaoka 120a6e
  void endLine();
Shinya Kitaoka 473e70
  void onActivate() override;
Shinya Kitaoka 473e70
  void onDeactivate() override {
Shinya Kitaoka 120a6e
    m_vertex.clear();
Shinya Kitaoka 120a6e
    m_speedMoved       = false;
Shinya Kitaoka 120a6e
    m_beforeSpeedMoved = false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 473e70
  void onEnter() override;
Shinya Kitaoka 473e70
  void onImageChanged() override;
Shinya Kitaoka 120a6e
  void setVertexes(const std::vector<tpointd> &vertex) { m_vertex = vertex; };</tpointd>
Shinya Kitaoka 120a6e
  void setSpeedMoved(bool speedMoved) { m_speedMoved = speedMoved; };
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MultilinePrimitiveUndo::undo() const {
Shinya Kitaoka 120a6e
  m_tool->setVertexes(m_oldVertex);
Shinya Kitaoka 120a6e
  int count       = m_oldVertex.size();
Shinya Kitaoka 120a6e
  bool speedMoved = (count != 0 && count % 4 != 1);
Shinya Kitaoka 120a6e
  m_tool->setSpeedMoved(speedMoved);
Shinya Kitaoka 120a6e
  TTool::getApplication()->getCurrentTool()->getTool()->invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MultilinePrimitiveUndo::redo() const {
Shinya Kitaoka 120a6e
  m_tool->setVertexes(m_newVertex);
Shinya Kitaoka 120a6e
  int count       = m_newVertex.size();
Shinya Kitaoka 120a6e
  bool speedMoved = (count != 0 && count % 4 != 1);
Shinya Kitaoka 120a6e
  m_tool->setSpeedMoved(speedMoved);
Shinya Kitaoka 120a6e
  TTool::getApplication()->getCurrentTool()->getTool()->invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QString MultilinePrimitiveUndo::getToolName() {
Shinya Kitaoka 120a6e
  return QString("Geometric Tool %1")
Shinya Kitaoka 120a6e
      .arg(QString::fromStdString(m_tool->getName()));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Line Primitive Class Declaration
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class LinePrimitive final : public MultiLinePrimitive {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  LinePrimitive(PrimitiveParam *param, GeometricTool *tool, bool reasterTool)
Shinya Kitaoka 120a6e
      : MultiLinePrimitive(param, tool, reasterTool) {
Shinya Kitaoka 120a6e
    m_isSingleLine = true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  std::string getName() const override {
Shinya Kitaoka 120a6e
    return "Line";
Shinya Kitaoka 120a6e
  }  // W_ToolOptions_ShapePolyline";}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void draw() override;
Shinya Kitaoka 473e70
  void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override;
Shinya Kitaoka 473e70
  void leftButtonUp(const TPointD &pos, const TMouseEvent &e) override;
Shinya Kitaoka 473e70
  void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override;
Shinya Kitaoka 473e70
  void leftButtonDoubleClick(const TPointD &, const TMouseEvent &e) override {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Ellipse Primitive Class Declaration
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class EllipsePrimitive final : public Primitive {
Shinya Kitaoka 120a6e
  TPointD m_pos;
Shinya Kitaoka 120a6e
  TRectD m_selectingRect;
Shinya Kitaoka 120a6e
  TPointD m_startPoint;
Shinya Kitaoka 120a6e
  TPixel32 m_color;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  EllipsePrimitive(PrimitiveParam *param, GeometricTool *tool, bool reasterTool)
Shinya Kitaoka 120a6e
      : Primitive(param, tool, reasterTool) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  std::string getName() const override {
Shinya Kitaoka 120a6e
    return "Ellipse";
Shinya Kitaoka 120a6e
  }  // W_ToolOptions_ShapeEllipse";}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void draw() override;
Shinya Kitaoka 473e70
  void leftButtonDown(const TPointD &pos, const TMouseEvent &) override;
Shinya Kitaoka 473e70
  void leftButtonDrag(const TPointD &realPos, const TMouseEvent &e) override;
Shinya Kitaoka 473e70
  TStroke *makeStroke() const 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;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Arc Primitive Class Declaration
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class ArcPrimitive final : public Primitive {
Shinya Kitaoka 120a6e
  TStroke *m_stroke;
Shinya Kitaoka 120a6e
  TPointD m_startPoint, m_endPoint, m_centralPoint;
Shinya Kitaoka 120a6e
  int m_clickNumber;
Shinya Kitaoka 120a6e
  TPixel32 m_color;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  ArcPrimitive(PrimitiveParam *param, GeometricTool *tool, bool reasterTool)
Shinya Kitaoka 120a6e
      : Primitive(param, tool, reasterTool), m_stroke(0), m_clickNumber(0) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~ArcPrimitive() {
Shinya Kitaoka 120a6e
    if (m_stroke) delete m_stroke;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  std::string getName() const override {
Shinya Kitaoka 120a6e
    return "Arc";
Shinya Kitaoka 120a6e
  }  // _ToolOptions_ShapeArc";}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  TStroke *makeStroke() const override;
Shinya Kitaoka 473e70
  void draw() 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;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Polygon Primitive Class Declaration
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class PolygonPrimitive final : public Primitive {
Shinya Kitaoka 120a6e
  TPointD m_startPoint, m_centre;
Shinya Kitaoka 120a6e
  double m_radius;
Shinya Kitaoka 120a6e
  TPixel32 m_color;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  PolygonPrimitive(PrimitiveParam *param, GeometricTool *tool, bool reasterTool)
Shinya Kitaoka 120a6e
      : Primitive(param, tool, reasterTool) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  std::string getName() const override {
Shinya Kitaoka 120a6e
    return "Polygon";
Shinya Kitaoka 120a6e
  }  // W_ToolOptions_ShapePolygon";}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  TStroke *makeStroke() const override;
Shinya Kitaoka 473e70
  void draw() override;
Shinya Kitaoka 473e70
  void leftButtonDown(const TPointD &pos, const TMouseEvent &) override;
Shinya Kitaoka 473e70
  void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override;
Shinya Kitaoka 473e70
  void leftButtonUp(const TPointD &pos, const TMouseEvent &) override;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Geometric Tool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class GeometricTool final : public TTool {
Toshihiro Shimizu 890ddd
protected:
Shinya Kitaoka 120a6e
  Primitive *m_primitive;
Shinya Kitaoka 120a6e
  std::map<std::wstring, *="" primitive=""> m_primitiveTable;</std::wstring,>
Shinya Kitaoka 120a6e
  PrimitiveParam m_param;
Shinya Kitaoka 120a6e
  std::wstring m_typeCode;
Shinya Kitaoka 120a6e
  bool m_active;
Shinya Kitaoka 120a6e
  bool m_firstTime;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  GeometricTool(int targetType)
Shinya Kitaoka 120a6e
      : TTool("T_Geometric")
Shinya Kitaoka 120a6e
      , m_primitive(0)
Shinya Kitaoka 120a6e
      , m_param(targetType)
Shinya Kitaoka 120a6e
      , m_active(false)
Shinya Kitaoka 120a6e
      , m_firstTime(true) {
Shinya Kitaoka 120a6e
    bind(targetType);
Shinya Kitaoka 120a6e
    if ((targetType & TTool::RasterImage) || (targetType & TTool::ToonzImage)) {
Shinya Kitaoka 120a6e
      addPrimitive(new RectanglePrimitive(&m_param, this, true));
Shinya Kitaoka 120a6e
      addPrimitive(new CirclePrimitive(&m_param, this, true));
Shinya Kitaoka 120a6e
      addPrimitive(new EllipsePrimitive(&m_param, this, true));
Shinya Kitaoka 120a6e
      addPrimitive(new LinePrimitive(&m_param, this, true));
Shinya Kitaoka 120a6e
      addPrimitive(new MultiLinePrimitive(&m_param, this, true));
Shinya Kitaoka 120a6e
      addPrimitive(new ArcPrimitive(&m_param, this, true));
Shinya Kitaoka 120a6e
      addPrimitive(new PolygonPrimitive(&m_param, this, true));
Shinya Kitaoka 120a6e
    } else  // targetType == 1
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      // vector
Shinya Kitaoka 120a6e
      addPrimitive(m_primitive = new RectanglePrimitive(&m_param, this, false));
Shinya Kitaoka 120a6e
      addPrimitive(new CirclePrimitive(&m_param, this, false));
Shinya Kitaoka 120a6e
      addPrimitive(new EllipsePrimitive(&m_param, this, false));
Shinya Kitaoka 120a6e
      addPrimitive(new LinePrimitive(&m_param, this, false));
Shinya Kitaoka 120a6e
      addPrimitive(new MultiLinePrimitive(&m_param, this, false));
Shinya Kitaoka 120a6e
      addPrimitive(new ArcPrimitive(&m_param, this, false));
Shinya Kitaoka 120a6e
      addPrimitive(new PolygonPrimitive(&m_param, this, false));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~GeometricTool() {
Shinya Kitaoka 120a6e
    std::map<std::wstring, *="" primitive="">::iterator it;</std::wstring,>
Shinya Kitaoka 120a6e
    for (it = m_primitiveTable.begin(); it != m_primitiveTable.end(); ++it)
Shinya Kitaoka 120a6e
      delete it->second;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  ToolType getToolType() const override { return TTool::LevelWriteTool; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void updateTranslation() override { m_param.updateTranslation(); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void addPrimitive(Primitive *p) {
Shinya Kitaoka 120a6e
    // TODO: aggiungere il controllo per evitare nomi ripetuti
Shinya Kitaoka 120a6e
    std::wstring name = ::to_wstring(p->getName());
Shinya Kitaoka 120a6e
    // wstring name = TStringTable::translate(p->getName());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_primitiveTable[name] = p;
Shinya Kitaoka 120a6e
    m_param.m_type.addValue(name);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void changeType(std::wstring name) {
Shinya Kitaoka 120a6e
    std::map<std::wstring, *="" primitive="">::iterator it =</std::wstring,>
Shinya Kitaoka 120a6e
        m_primitiveTable.find(name);
Shinya Kitaoka 120a6e
    if (it != m_primitiveTable.end()) m_primitive = it->second;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void leftButtonDown(const TPointD &p, const TMouseEvent &e) override {
Shinya Kitaoka 120a6e
    /* m_active = getApplication()->getCurrentObject()->isSpline() ||
Shinya Kitaoka 120a6e
   (bool) getImage(true);*/
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_active = touchImage();  // NEEDS to be done even if(m_active), due
Shinya Kitaoka 120a6e
    if (!m_active)            // to the HORRIBLE m_frameCreated / m_levelCreated
Shinya Kitaoka 120a6e
      return;                 // mechanism. touchImage() is the ONLY function
Shinya Kitaoka 120a6e
    // resetting them to false...                       >_<
Shinya Kitaoka 120a6e
    if (m_primitive) m_primitive->leftButtonDown(p, e);
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 473e70
  void leftButtonDrag(const TPointD &p, const TMouseEvent &e) override {
Shinya Kitaoka 120a6e
    if (!m_active) return;
Shinya Kitaoka 120a6e
    if (m_primitive) m_primitive->leftButtonDrag(p, e);
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 473e70
  void leftButtonUp(const TPointD &p, const TMouseEvent &e) override {
Shinya Kitaoka 120a6e
    if (!m_active) return;
Shinya Kitaoka 120a6e
    if (m_primitive) m_primitive->leftButtonUp(p, e);
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 473e70
  void leftButtonDoubleClick(const TPointD &p, const TMouseEvent &e) override {
Shinya Kitaoka 120a6e
    if (!m_active) return;
Shinya Kitaoka 120a6e
    if (m_primitive) m_primitive->leftButtonDoubleClick(p, e);
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  bool keyDown(int key, TUINT32 b, const TPoint &point) override {
Shinya Kitaoka 120a6e
    return m_primitive->keyDown(key, point);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void onImageChanged() override {
Shinya Kitaoka 120a6e
    if (m_primitive) m_primitive->onImageChanged();
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void rightButtonDown(const TPointD &p, const TMouseEvent &e) override {
Shinya Kitaoka 120a6e
    if (m_primitive) m_primitive->rightButtonDown(p, e);
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void mouseMove(const TPointD &p, const TMouseEvent &e) override {
Shinya Kitaoka 120a6e
    if (m_primitive) m_primitive->mouseMove(p, e);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void onActivate() override {
Shinya Kitaoka 120a6e
    if (m_firstTime) {
Shinya Kitaoka 120a6e
      m_param.m_toolSize.setValue(GeometricSize);
Shinya Kitaoka 120a6e
      m_param.m_rasterToolSize.setValue(GeometricRasterSize);
Shinya Kitaoka 120a6e
      m_param.m_opacity.setValue(GeometricOpacity);
Shinya Kitaoka 120a6e
      m_param.m_hardness.setValue(GeometricBrushHardness);
Shinya Kitaoka 120a6e
      m_param.m_selective.setValue(GeometricSelective ? 1 : 0);
Shinya Kitaoka 120a6e
      m_param.m_autogroup.setValue(GeometricGroupIt ? 1 : 0);
Shinya Kitaoka 120a6e
      m_param.m_autofill.setValue(GeometricAutofill ? 1 : 0);
Shinya Kitaoka 120a6e
      std::wstring typeCode = ::to_wstring(GeometricType.getValue());
Shinya Kitaoka 120a6e
      m_param.m_type.setValue(typeCode);
Shinya Kitaoka 120a6e
      GeometricType = ::to_string(typeCode);
Shinya Kitaoka 120a6e
      m_typeCode    = typeCode;
Shinya Kitaoka 120a6e
      changeType(typeCode);
Shinya Kitaoka 120a6e
      m_param.m_edgeCount.setValue(GeometricEdgeCount);
Shinya Kitaoka 120a6e
      m_param.m_pencil.setValue(GeometricPencil ? 1 : 0);
Shinya Kitaoka 120a6e
      m_param.m_capStyle.setIndex(GeometricCapStyle);
Shinya Kitaoka 120a6e
      m_param.m_joinStyle.setIndex(GeometricJoinStyle);
Shinya Kitaoka 120a6e
      m_param.m_miterJoinLimit.setValue(GeometricMiterValue);
Shinya Kitaoka 120a6e
      m_firstTime = false;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    /*--
Shinya Kitaoka 120a6e
       ショートカットでいきなりスタート(=onEnterを通らない場合)のとき、
Shinya Kitaoka 120a6e
            LineToolが反応しないことがある対策 --*/
Shinya Kitaoka 120a6e
    m_active = (getImage(false) != 0 ||
Shinya Kitaoka 120a6e
                Preferences::instance()->isAutoCreateEnabled());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_primitive) m_primitive->onActivate();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void onDeactivate() override {
Shinya Kitaoka 120a6e
    if (m_primitive) m_primitive->onDeactivate();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void onEnter() override {
Shinya Kitaoka 120a6e
    m_active = getImage(false) != 0;
Shinya Kitaoka 120a6e
    if (m_active && m_primitive) m_primitive->onEnter();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void draw() override {
Shinya Kitaoka 120a6e
    if (m_primitive) m_primitive->draw();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  int getCursorId() const override { return ToolCursor::PenCursor; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int getColorClass() const { return 1; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  TPropertyGroup *getProperties(int idx) override {
Shinya Kitaoka 38fd86
    return &m_param.m_prop[idx];
Shinya Kitaoka 38fd86
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  bool onPropertyChanged(std::string propertyName) override {
Shinya Kitaoka 120a6e
    /*---	変更されたPropertyごとに処理を分ける。
Shinya Kitaoka 120a6e
            注意:m_toolSizeとm_rasterToolSizeは同じName(="Size:")なので、
Shinya Kitaoka 120a6e
            扱っている画像がラスタかどうかで区別する ---*/
Shinya Kitaoka 120a6e
    if (propertyName == m_param.m_toolSize.getName()) {
Shinya Kitaoka 120a6e
      TImageP img = getImage(false);
Shinya Kitaoka 120a6e
      TToonzImageP ri(img); /*-- ラスタかどうかの判定 --*/
Shinya Kitaoka 120a6e
      if (ri)
Shinya Kitaoka 120a6e
        GeometricRasterSize = m_param.m_rasterToolSize.getValue();
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        GeometricSize = m_param.m_toolSize.getValue();
Shinya Kitaoka 120a6e
    } else if (propertyName == m_param.m_type.getName()) {
Shinya Kitaoka 120a6e
      std::wstring typeCode = m_param.m_type.getValue();
Shinya Kitaoka 120a6e
      GeometricType         = ::to_string(typeCode);
Shinya Kitaoka 120a6e
      if (typeCode != m_typeCode) {
Shinya Kitaoka 120a6e
        m_typeCode = typeCode;
Shinya Kitaoka 120a6e
        changeType(typeCode);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else if (propertyName == m_param.m_edgeCount.getName())
Shinya Kitaoka 120a6e
      GeometricEdgeCount = m_param.m_edgeCount.getValue();
Shinya Kitaoka 120a6e
    else if (propertyName == m_param.m_autogroup.getName()) {
Shinya Kitaoka 120a6e
      if (!m_param.m_autogroup.getValue()) {
Shinya Kitaoka 120a6e
        m_param.m_autofill.setValue(false);
Shinya Kitaoka 120a6e
        // this is ugly: it's needed to refresh the GUI of the toolbar after
Shinya Kitaoka 120a6e
        // having set to false the autofill...
Shinya Kitaoka 120a6e
        TTool::getApplication()->getCurrentTool()->setTool(
Shinya Kitaoka 120a6e
            "");  // necessary, otherwise next setTool is ignored...
Shinya Kitaoka 120a6e
        TTool::getApplication()->getCurrentTool()->setTool(
Shinya Kitaoka 120a6e
            QString::fromStdString(getName()));
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      GeometricGroupIt = m_param.m_autogroup.getValue();
Shinya Kitaoka 120a6e
    } else if (propertyName == m_param.m_autofill.getName()) {
Shinya Kitaoka 120a6e
      if (m_param.m_autofill.getValue()) {
Shinya Kitaoka 120a6e
        m_param.m_autogroup.setValue(true);
Shinya Kitaoka 120a6e
        // this is ugly: it's needed to refresh the GUI of the toolbar after
Shinya Kitaoka 120a6e
        // having set to false the autofill...
Shinya Kitaoka 120a6e
        TTool::getApplication()->getCurrentTool()->setTool(
Shinya Kitaoka 120a6e
            "");  // necessary, otherwise next setTool is ignored...
Shinya Kitaoka 120a6e
        TTool::getApplication()->getCurrentTool()->setTool(
Shinya Kitaoka 120a6e
            QString::fromStdString(getName()));
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      GeometricGroupIt = m_param.m_autofill.getValue();
Shinya Kitaoka 120a6e
    } else if (propertyName == m_param.m_selective.getName())
Shinya Kitaoka 120a6e
      GeometricSelective = m_param.m_selective.getValue();
Shinya Kitaoka 120a6e
    else if (propertyName == m_param.m_pencil.getName())
Shinya Kitaoka 120a6e
      GeometricPencil = m_param.m_pencil.getValue();
Shinya Kitaoka 120a6e
    else if (propertyName == m_param.m_hardness.getName())
Shinya Kitaoka 120a6e
      GeometricBrushHardness = m_param.m_hardness.getValue();
Shinya Kitaoka 120a6e
    else if (propertyName == m_param.m_opacity.getName())
Shinya Kitaoka 120a6e
      GeometricOpacity = m_param.m_opacity.getValue();
Shinya Kitaoka 120a6e
    else if (propertyName == m_param.m_capStyle.getName())
Shinya Kitaoka 120a6e
      GeometricCapStyle = m_param.m_capStyle.getIndex();
Shinya Kitaoka 120a6e
    else if (propertyName == m_param.m_joinStyle.getName())
Shinya Kitaoka 120a6e
      GeometricJoinStyle = m_param.m_joinStyle.getIndex();
Shinya Kitaoka 120a6e
    else if (propertyName == m_param.m_miterJoinLimit.getName())
Shinya Kitaoka 120a6e
      GeometricMiterValue = m_param.m_miterJoinLimit.getValue();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void addStroke() {
Shinya Kitaoka 120a6e
    if (!m_primitive) return;
Shinya Kitaoka 120a6e
    TStroke *stroke = m_primitive->makeStroke();
Shinya Kitaoka 120a6e
    if (!stroke) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TStroke::OutlineOptions &options = stroke->outlineOptions();
Shinya Kitaoka 120a6e
    options.m_capStyle               = m_param.m_capStyle.getIndex();
Shinya Kitaoka 120a6e
    options.m_joinStyle              = m_param.m_joinStyle.getIndex();
Shinya Kitaoka 120a6e
    options.m_miterUpper             = m_param.m_miterJoinLimit.getValue();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TImage *image = getImage(true);
Shinya Kitaoka 120a6e
    TToonzImageP ti(image);
Shinya Kitaoka 120a6e
    TVectorImageP vi(image);
Shinya Kitaoka 120a6e
    TRasterImageP ri(image);
Shinya Kitaoka 120a6e
    TXshSimpleLevel *sl =
Shinya Kitaoka 120a6e
        TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Shinya Kitaoka 120a6e
    TFrameId id = getCurrentFid();
Shinya Kitaoka 120a6e
    /*-- ToonzImageの場合 --*/
Shinya Kitaoka 120a6e
    if (ti) {
Shinya Kitaoka 120a6e
      int styleId    = TTool::getApplication()->getCurrentLevelStyleIndex();
Shinya Kitaoka 120a6e
      bool selective = m_param.m_selective.getValue();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      bool filled = false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      stroke->setStyle(styleId);
Shinya Kitaoka 120a6e
      double hardness = m_param.m_hardness.getValue() * 0.01;
Shinya Kitaoka 120a6e
      TRect savebox;
Shinya Kitaoka 120a6e
      if (hardness == 1 || m_param.m_pencil.getValue()) {
Shinya Kitaoka 120a6e
        TUndoManager::manager()->add(new UndoRasterPencil(
Shinya Kitaoka 120a6e
            sl, id, stroke, selective, filled, !m_param.m_pencil.getValue(),
Shinya Kitaoka 120a6e
            m_isFrameCreated, m_isLevelCreated, m_primitive->getName()));
Shinya Kitaoka 120a6e
        savebox = ToonzImageUtils::addInkStroke(ti, stroke, styleId, selective,
Shinya Kitaoka 120a6e
                                                filled, TConsts::infiniteRectD,
Shinya Kitaoka 120a6e
                                                !m_param.m_pencil.getValue());
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        int thickness = m_param.m_rasterToolSize.getValue();
Shinya Kitaoka 120a6e
        TUndoManager::manager()->add(new CMBluredPrimitiveUndo(
Shinya Kitaoka 120a6e
            sl, id, stroke, thickness, hardness, selective, false,
Shinya Kitaoka 120a6e
            m_isFrameCreated, m_isLevelCreated, m_primitive->getName()));
Shinya Kitaoka 120a6e
        savebox = drawBluredBrush(ti, stroke, thickness, hardness, selective);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      ToolUtils::updateSaveBox();
Shinya Kitaoka 120a6e
      delete stroke;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    /*-- VectorImageの場合 --*/
Shinya Kitaoka 120a6e
    else if (vi) {
Shinya Kitaoka 120a6e
      if (TTool::getApplication()->getCurrentObject()->isSpline()) {
Shinya Kitaoka 120a6e
        if (!ToolUtils::isJustCreatedSpline(vi.getPointer())) {
Shinya Kitaoka 120a6e
          m_primitive->setIsPrompting(true);
Shinya Kitaoka 120a6e
          QString question("Are you sure you want to replace the motion path?");
Shinya Kitaoka 120a6e
          int ret =
Shinya Kitaoka 120a6e
              DVGui::MsgBox(question, QObject::tr("Yes"), QObject::tr("No"), 0);
Shinya Kitaoka 120a6e
          m_primitive->setIsPrompting(false);
Shinya Kitaoka 120a6e
          if (ret == 2 || ret == 0) return;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        TUndo *undo = new UndoPath(
Shinya Kitaoka 120a6e
            getXsheet()->getStageObject(getObjectId())->getSpline());
Shinya Kitaoka 120a6e
        while (vi->getStrokeCount() > 0) vi->deleteStroke(0);
Shinya Kitaoka 120a6e
        vi->addStroke(stroke, false);
Shinya Kitaoka 120a6e
        notifyImageChanged();
Shinya Kitaoka 120a6e
        TUndoManager::manager()->add(undo);
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        int styleId = TTool::getApplication()->getCurrentLevelStyleIndex();
Shinya Kitaoka 120a6e
        if (styleId >= 0) stroke->setStyle(styleId);
Shinya Kitaoka 120a6e
        QMutexLocker lock(vi->getMutex());
Shinya Kitaoka 120a6e
        std::vector<tfilledregioninf> *fillInformation =</tfilledregioninf>
Shinya Kitaoka 120a6e
            new std::vector<tfilledregioninf>;</tfilledregioninf>
Shinya Kitaoka 120a6e
        ImageUtils::getFillingInformationOverlappingArea(vi, *fillInformation,
Shinya Kitaoka 120a6e
                                                         stroke->getBBox());
Shinya Kitaoka 120a6e
        vi->addStroke(stroke);
Shinya Kitaoka 120a6e
        TUndoManager::manager()->add(new UndoPencil(
Shinya Kitaoka 120a6e
            vi->getStroke(vi->getStrokeCount() - 1), fillInformation, sl, id,
Shinya Kitaoka 120a6e
            m_isFrameCreated, m_isLevelCreated, m_param.m_autogroup.getValue(),
Shinya Kitaoka 120a6e
            m_param.m_autofill.getValue()));
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (m_param.m_autogroup.getValue() && stroke->isSelfLoop()) {
Shinya Kitaoka 120a6e
        int index = vi->getStrokeCount() - 1;
Shinya Kitaoka 120a6e
        vi->group(index, 1);
Shinya Kitaoka 120a6e
        if (m_param.m_autofill.getValue()) {
Shinya Kitaoka 120a6e
          // to avoid filling other strokes, I enter into the new stroke group
Shinya Kitaoka 120a6e
          int currentGroup = vi->exitGroup();
Shinya Kitaoka 120a6e
          vi->enterGroup(index);
Shinya Kitaoka 120a6e
          vi->selectFill(stroke->getBBox().enlarge(1, 1), 0, stroke->getStyle(),
Shinya Kitaoka 120a6e
                         false, true, false);
Shinya Kitaoka 120a6e
          if (currentGroup != -1)
Shinya Kitaoka 120a6e
            vi->enterGroup(currentGroup);
Shinya Kitaoka 120a6e
          else
Shinya Kitaoka 120a6e
            vi->exitGroup();
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    /*-- RasterImageの場合 --*/
Shinya Kitaoka 120a6e
    else if (ri) {
Shinya Kitaoka 120a6e
      int styleId = TTool::getApplication()->getCurrentLevelStyleIndex();
Shinya Kitaoka 120a6e
      stroke->setStyle(styleId);
Shinya Kitaoka 120a6e
      double opacity  = m_param.m_opacity.getValue() * 0.01;
Shinya Kitaoka 120a6e
      double hardness = m_param.m_hardness.getValue() * 0.01;
Shinya Kitaoka 120a6e
      TRect savebox;
Shinya Kitaoka 120a6e
      if (hardness == 1) {
Shinya Kitaoka 120a6e
        TUndoManager::manager()->add(new UndoFullColorPencil(
Shinya Kitaoka 120a6e
            sl, id, stroke, opacity, true, m_isFrameCreated, m_isLevelCreated));
Shinya Kitaoka 120a6e
        savebox = TRasterImageUtils::addStroke(ri, stroke, TRectD(), opacity);
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        int thickness = m_param.m_rasterToolSize.getValue();
Shinya Kitaoka 120a6e
        TUndoManager::manager()->add(new FullColorBluredPrimitiveUndo(
Shinya Kitaoka 120a6e
            sl, id, stroke, thickness, hardness, opacity, true,
Shinya Kitaoka 120a6e
            m_isFrameCreated, m_isLevelCreated));
Shinya Kitaoka 120a6e
        savebox = drawBluredBrush(ri, stroke, thickness, hardness, opacity);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      ToolUtils::updateSaveBox();
Shinya Kitaoka 120a6e
      delete stroke;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    notifyImageChanged();
Shinya Kitaoka 120a6e
    m_active = false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
GeometricTool GeometricVectorTool(TTool::Vectors | TTool::EmptyTarget);
Toshihiro Shimizu 890ddd
GeometricTool GeometricRasterTool(TTool::ToonzImage | TTool::EmptyTarget);
Shinya Kitaoka 120a6e
GeometricTool GeometricRasterFullColorTool(TTool::RasterImage |
Shinya Kitaoka 120a6e
                                           TTool::EmptyTarget);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Rectangle Primitive Class Implementation
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RectanglePrimitive::draw() {
Shinya Kitaoka 120a6e
  if (m_isEditing || m_isPrompting ||
Shinya Kitaoka 120a6e
      areAlmostEqual(m_selectingRect.x0, m_selectingRect.x1) ||
Shinya Kitaoka 120a6e
      areAlmostEqual(m_selectingRect.y0, m_selectingRect.y1)) {
Shinya Kitaoka 120a6e
    tglColor(m_isEditing ? m_color : TPixel32::Green);
Shinya Kitaoka 120a6e
    glBegin(GL_LINE_LOOP);
Shinya Kitaoka 120a6e
    tglVertex(m_selectingRect.getP00());
Shinya Kitaoka 120a6e
    tglVertex(m_selectingRect.getP01());
Shinya Kitaoka 120a6e
    tglVertex(m_selectingRect.getP11());
Shinya Kitaoka 120a6e
    tglVertex(m_selectingRect.getP10());
Shinya Kitaoka 120a6e
    glEnd();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RectanglePrimitive::leftButtonDown(const TPointD &pos,
Shinya Kitaoka 120a6e
                                        const TMouseEvent &) {
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (app->getCurrentObject()->isSpline()) {
Shinya Kitaoka 120a6e
    m_color     = TPixel32::Red;
Shinya Kitaoka 120a6e
    m_isEditing = true;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    // app->getCurrentTool()->getTool()->touchImage();
Shinya Kitaoka 120a6e
    const TColorStyle *style = app->getCurrentLevelStyle();
Shinya Kitaoka 120a6e
    m_isEditing              = style != 0 && style->isStrokeStyle();
Shinya Kitaoka 120a6e
    m_color = (style) ? style->getAverageColor() : TPixel32::Black;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_isEditing) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_param->m_pencil.getValue() &&
Shinya Kitaoka 120a6e
      (m_param->m_targetType & TTool::ToonzImage ||
Shinya Kitaoka 120a6e
       m_param->m_targetType & TTool::RasterImage)) {
Shinya Kitaoka 120a6e
    if (m_param->m_rasterToolSize.getValue() % 2 != 0)
Shinya Kitaoka 120a6e
      m_startPoint = TPointD((int)pos.x, (int)pos.y);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      m_startPoint = TPointD((int)pos.x + 0.5, (int)pos.y + 0.5);
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    m_startPoint     = pos;
Shinya Kitaoka 120a6e
  m_selectingRect.x0 = m_startPoint.x;
Shinya Kitaoka 120a6e
  m_selectingRect.y0 = m_startPoint.y;
Shinya Kitaoka 120a6e
  m_selectingRect.x1 = m_startPoint.x;
Shinya Kitaoka 120a6e
  m_selectingRect.y1 = m_startPoint.y;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RectanglePrimitive::leftButtonDrag(const TPointD &realPos,
Shinya Kitaoka 120a6e
                                        const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  if (!m_isEditing) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD pos;
Shinya Kitaoka 120a6e
  if (e.isShiftPressed()) {
Shinya Kitaoka 120a6e
    double distance = tdistance(realPos, m_startPoint) * M_SQRT1_2;
Shinya Kitaoka 120a6e
    pos.x           = (realPos.x > m_startPoint.x) ? m_startPoint.x + distance
Shinya Kitaoka 120a6e
                                         : m_startPoint.x - distance;
Shinya Kitaoka 120a6e
    pos.y = (realPos.y > m_startPoint.y) ? m_startPoint.y + distance
Shinya Kitaoka 120a6e
                                         : m_startPoint.y - distance;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    pos = realPos;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_param->m_pencil.getValue() &&
Shinya Kitaoka 120a6e
      (m_param->m_targetType & TTool::ToonzImage ||
Shinya Kitaoka 120a6e
       m_param->m_targetType & TTool::RasterImage)) {
Shinya Kitaoka 120a6e
    if (m_param->m_rasterToolSize.getValue() % 2 != 0)
Shinya Kitaoka 120a6e
      pos = TPointD((int)pos.x, (int)pos.y);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      pos = TPointD((int)pos.x + 0.5, (int)pos.y + 0.5);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_selectingRect.x1 = pos.x;
Shinya Kitaoka 120a6e
  m_selectingRect.y1 = pos.y;
Shinya Kitaoka 120a6e
  if (!e.isAltPressed()) {
Shinya Kitaoka 120a6e
    m_selectingRect.x0 = m_startPoint.x;
Shinya Kitaoka 120a6e
    m_selectingRect.y0 = m_startPoint.y;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    m_selectingRect.x0 = m_startPoint.x + m_startPoint.x - pos.x;
Shinya Kitaoka 120a6e
    m_selectingRect.y0 = m_startPoint.y + m_startPoint.y - pos.y;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStroke *RectanglePrimitive::makeStroke() const {
Shinya Kitaoka 120a6e
  if (areAlmostEqual(m_selectingRect.x0, m_selectingRect.x1) ||
Shinya Kitaoka 120a6e
      areAlmostEqual(m_selectingRect.y0, m_selectingRect.y1))
Shinya Kitaoka 120a6e
    return 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD selArea;
Shinya Kitaoka 120a6e
  selArea.x0 = std::min(m_selectingRect.x0, m_selectingRect.x1);
Shinya Kitaoka 120a6e
  selArea.y0 = std::min(m_selectingRect.y0, m_selectingRect.y1);
Shinya Kitaoka 120a6e
  selArea.x1 = std::max(m_selectingRect.x0, m_selectingRect.x1);
Shinya Kitaoka 120a6e
  selArea.y1 = std::max(m_selectingRect.y0, m_selectingRect.y1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double thick = getThickness();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TStroke *stroke = 0;
Shinya Kitaoka 120a6e
  if (m_param->m_targetType & TTool::Vectors) {
Shinya Kitaoka 120a6e
    std::vector<tthickpoint> points(17);</tthickpoint>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    points[0] = TThickPoint(selArea.x1, selArea.y1, thick);
Shinya Kitaoka 120a6e
    points[1] = TThickPoint(selArea.x1, selArea.y1, thick) + TPointD(-0.01, 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    points[3] = TThickPoint(selArea.x0, selArea.y1, thick) + TPointD(0.01, 0);
Shinya Kitaoka 120a6e
    points[4] = TThickPoint(selArea.x0, selArea.y1, thick);
Shinya Kitaoka 120a6e
    points[5] = TThickPoint(selArea.x0, selArea.y1, thick) + TPointD(0, -0.01);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    points[7] = TThickPoint(selArea.x0, selArea.y0, thick) + TPointD(0, 0.01);
Shinya Kitaoka 120a6e
    points[8] = TThickPoint(selArea.x0, selArea.y0, thick);
Shinya Kitaoka 120a6e
    points[9] = TThickPoint(selArea.x0, selArea.y0, thick) + TPointD(0.01, 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    points[11] = TThickPoint(selArea.x1, selArea.y0, thick) + TPointD(-0.01, 0);
Shinya Kitaoka 120a6e
    points[12] = TThickPoint(selArea.x1, selArea.y0, thick);
Shinya Kitaoka 120a6e
    points[13] = TThickPoint(selArea.x1, selArea.y0, thick) + TPointD(0, 0.01);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    points[15] = points[0] + TPointD(0, -0.01);
Shinya Kitaoka 120a6e
    points[16] = points[0];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    points[2]  = 0.5 * (points[1] + points[3]);
Shinya Kitaoka 120a6e
    points[6]  = 0.5 * (points[5] + points[7]);
Shinya Kitaoka 120a6e
    points[10] = 0.5 * (points[9] + points[11]);
Shinya Kitaoka 120a6e
    points[14] = 0.5 * (points[13] + points[15]);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    stroke = new TStroke(points);
Shinya Kitaoka 120a6e
  } else if (m_param->m_targetType & TTool::ToonzImage ||
Shinya Kitaoka 120a6e
             m_param->m_targetType & TTool::RasterImage) {
Shinya Kitaoka 120a6e
    std::vector<tthickpoint> points(9);</tthickpoint>
Shinya Kitaoka 120a6e
    double middleX = (selArea.x0 + selArea.x1) * 0.5;
Shinya Kitaoka 120a6e
    double middleY = (selArea.y0 + selArea.y1) * 0.5;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    points[0] = TThickPoint(selArea.x1, selArea.y1, thick);
Shinya Kitaoka 120a6e
    points[1] = TThickPoint(middleX, selArea.y1, thick);
Shinya Kitaoka 120a6e
    points[2] = TThickPoint(selArea.x0, selArea.y1, thick);
Shinya Kitaoka 120a6e
    points[3] = TThickPoint(selArea.x0, middleY, thick);
Shinya Kitaoka 120a6e
    points[4] = TThickPoint(selArea.x0, selArea.y0, thick);
Shinya Kitaoka 120a6e
    points[5] = TThickPoint(middleX, selArea.y0, thick);
Shinya Kitaoka 120a6e
    points[6] = TThickPoint(selArea.x1, selArea.y0, thick);
Shinya Kitaoka 120a6e
    points[7] = TThickPoint(selArea.x1, middleY, thick);
Shinya Kitaoka 120a6e
    points[8] = points[0];
Shinya Kitaoka 120a6e
    stroke    = new TStroke(points);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  stroke->setSelfLoop();
Shinya Kitaoka 120a6e
  return stroke;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RectanglePrimitive::leftButtonUp(const TPointD &pos, const TMouseEvent &) {
Shinya Kitaoka 120a6e
  if (!m_isEditing) return;
Shinya Kitaoka 120a6e
  m_isEditing = false;
Shinya Kitaoka 120a6e
  m_tool->addStroke();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RectanglePrimitive::mouseMove(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_pos = pos;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RectanglePrimitive::onEnter() {
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!app) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (app->getCurrentObject()->isSpline())
Shinya Kitaoka 120a6e
    m_color = TPixel32::Red;
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    const TColorStyle *style = app->getCurrentLevelStyle();
Shinya Kitaoka 120a6e
    if (style) m_color       = style->getAverageColor();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Circle Primitive Class Implementation
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CirclePrimitive::draw() {
Shinya Kitaoka 120a6e
  if (m_isEditing || m_isPrompting) {
Shinya Kitaoka 120a6e
    tglColor(m_isEditing ? m_color : TPixel32::Green);
Shinya Kitaoka 120a6e
    tglDrawCircle(m_centre, m_radius);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CirclePrimitive::leftButtonDown(const TPointD &pos, const TMouseEvent &) {
Shinya Kitaoka 120a6e
  m_pos    = pos;
Shinya Kitaoka 120a6e
  m_centre = pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!app) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (app->getCurrentObject()->isSpline()) {
Shinya Kitaoka 120a6e
    m_color     = TPixel32::Red;
Shinya Kitaoka 120a6e
    m_isEditing = true;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    const TColorStyle *style = app->getCurrentLevelStyle();
Shinya Kitaoka 120a6e
    if (style) {
Shinya Kitaoka 120a6e
      m_isEditing = style->isStrokeStyle();
Shinya Kitaoka 120a6e
      m_color     = style->getAverageColor();
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      m_isEditing = false;
Shinya Kitaoka 120a6e
      m_color     = TPixel32::Black;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_isEditing) return;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CirclePrimitive::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  if (!m_isEditing) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_pos    = pos;
Shinya Kitaoka 120a6e
  m_radius = tdistance(m_centre, pos);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStroke *CirclePrimitive::makeStroke() const {
Shinya Kitaoka 120a6e
  return makeEllipticStroke(getThickness(), m_centre, m_radius, m_radius);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CirclePrimitive::leftButtonUp(const TPointD &pos, const TMouseEvent &) {
Shinya Kitaoka 120a6e
  if (!m_isEditing) return;
Shinya Kitaoka 120a6e
  m_isEditing = false;
Shinya Kitaoka 120a6e
  if (isAlmostZero(m_radius)) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_tool->addStroke();
Shinya Kitaoka 120a6e
  m_radius = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CirclePrimitive::mouseMove(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_pos = pos;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CirclePrimitive::onEnter() {
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!app) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (app->getCurrentObject()->isSpline())
Shinya Kitaoka 120a6e
    m_color = TPixel32::Red;
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    const TColorStyle *style = app->getCurrentLevelStyle();
Shinya Kitaoka 120a6e
    if (style) m_color       = style->getAverageColor();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// MultiLine Primitive Class Implementation
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MultiLinePrimitive::addVertex(const TPointD &pos) {
Shinya Kitaoka 120a6e
  int count = m_vertex.size();
Shinya Kitaoka 120a6e
  // Inserisco il primo punto
Shinya Kitaoka 120a6e
  if (count == 0) {
Shinya Kitaoka 120a6e
    m_vertex.push_back(pos);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD &vertex = m_vertex[count - 1];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Caso particolare in cui inizio una curva e la chiudo subito cliccando sul
Shinya Kitaoka 120a6e
  // punto di pertenza
Shinya Kitaoka 120a6e
  if (count == 1 && pos == vertex) {
Shinya Kitaoka 120a6e
    m_vertex.push_back(pos);
Shinya Kitaoka 120a6e
    m_vertex.push_back(pos);
Shinya Kitaoka 120a6e
    m_vertex.push_back(pos);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Calcolo lo speedOut
Shinya Kitaoka 120a6e
  TPointD speedOutPoint;
Shinya Kitaoka 120a6e
  if (!m_speedMoved)  // Se non e' stato mosso lo speedOut devo calcolarlo e
Shinya Kitaoka 120a6e
                      // inserirlo
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    speedOutPoint = vertex + computeSpeed(vertex, pos, 0.01);
Shinya Kitaoka 120a6e
    m_vertex.push_back(speedOutPoint);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    if (m_ctrlDown)
Shinya Kitaoka 120a6e
      vertex =
Shinya Kitaoka 120a6e
          m_vertex[count - 2] + computeSpeed(m_vertex[count - 2], pos, 0.01);
Shinya Kitaoka 120a6e
    speedOutPoint = vertex;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Calcolo lo speedIn
Shinya Kitaoka 120a6e
  TPointD speedInPoint = pos + computeSpeed(pos, speedOutPoint, 0.01);
Shinya Kitaoka 120a6e
  // Calcolo il "punto di mezzo" e lo inserisco
Shinya Kitaoka 120a6e
  TPointD middlePoint = 0.5 * (speedInPoint + speedOutPoint);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Inserisco il "punto di mezzo"
Shinya Kitaoka 120a6e
  m_vertex.push_back(middlePoint);
Shinya Kitaoka 120a6e
  // Inserisco lo speedIn
Shinya Kitaoka 120a6e
  m_vertex.push_back(speedInPoint);
Shinya Kitaoka 120a6e
  // Inserisco il nuovo punto
Shinya Kitaoka 120a6e
  m_vertex.push_back(pos);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MultiLinePrimitive::moveSpeed(const TPointD &delta) {
Shinya Kitaoka 120a6e
  int count = m_vertex.size();
Shinya Kitaoka 120a6e
  assert(count > 0);
Shinya Kitaoka 120a6e
  TPointD lastPoint        = m_vertex[count - 1];
Shinya Kitaoka 120a6e
  TPointD newSpeedOutPoint = lastPoint - delta;
Shinya Kitaoka 120a6e
  if (m_speedMoved)
Shinya Kitaoka 120a6e
    m_vertex[count - 1] = newSpeedOutPoint;
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    m_vertex.push_back(newSpeedOutPoint);
Shinya Kitaoka 120a6e
    ++count;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (count < 5) {
Shinya Kitaoka 120a6e
    assert(count == 2);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD vertex = m_vertex[count - 2];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD v(0, 0);
Shinya Kitaoka 120a6e
  if (newSpeedOutPoint != vertex) v = normalize(newSpeedOutPoint - vertex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double speedOut         = tdistance(newSpeedOutPoint, vertex);
Shinya Kitaoka 120a6e
  TPointD newSpeedInPoint = vertex - TPointD(speedOut * v.x, speedOut * v.y);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_vertex[count - 3] = newSpeedInPoint;
Shinya Kitaoka 120a6e
  if (tdistance(m_vertex[count - 5], m_vertex[count - 6]) <= 0.02)
Shinya Kitaoka 120a6e
    // see ControlPointEditorStroke::isSpeedOutLinear() from
Shinya Kitaoka 120a6e
    // controlpointselection.cpp
Shinya Kitaoka 120a6e
    m_vertex[count - 5] =
Shinya Kitaoka 120a6e
        m_vertex[count - 6] +
Shinya Kitaoka 120a6e
        computeSpeed(m_vertex[count - 6], m_vertex[count - 3], 0.01);
Shinya Kitaoka 120a6e
  m_vertex[count - 4] = 0.5 * (m_vertex[count - 3] + m_vertex[count - 5]);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MultiLinePrimitive::draw() {
Shinya Kitaoka 120a6e
  UINT size = m_vertex.size();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if ((m_isEditing || m_isPrompting) && size > 0) {
Shinya Kitaoka 120a6e
    tglColor(m_isEditing ? m_color : TPixel32::Green);
Shinya Kitaoka 120a6e
    std::vector<tpointd> points;</tpointd>
Shinya Kitaoka 120a6e
    points.assign(m_vertex.begin(), m_vertex.end());
Shinya Kitaoka 120a6e
    int count = points.size();
Shinya Kitaoka 120a6e
    if (count % 4 == 1) {
Shinya Kitaoka 120a6e
      // No speedOut
Shinya Kitaoka 120a6e
      points.push_back(points[count - 1]);
Shinya Kitaoka 120a6e
      count++;
Shinya Kitaoka 120a6e
    } else if (m_ctrlDown)
Shinya Kitaoka 120a6e
      points[count - 1] = points[count - 2];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    points.push_back(0.5 * (m_mousePosition + points[count - 1]));
Shinya Kitaoka 120a6e
    points.push_back(m_mousePosition);
Shinya Kitaoka 120a6e
    points.push_back(m_mousePosition);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    double pixelSize = m_tool->getPixelSize();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TStroke *stroke = new TStroke(points);
Shinya Kitaoka 120a6e
    drawStrokeCenterline(*stroke, pixelSize);
Shinya Kitaoka 120a6e
    delete stroke;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_vertex.size() > 1) {
Shinya Kitaoka 120a6e
      tglColor(TPixel(79, 128, 255));
Shinya Kitaoka 120a6e
      int index = (count < 5) ? count - 1 : count - 5;
Shinya Kitaoka 120a6e
      // Disegno lo speedOut precedente (che e' quello corrente solo nel caso in
Shinya Kitaoka 120a6e
      // cui count < 5)
Shinya Kitaoka 120a6e
      TPointD p0 = m_vertex[index];
Shinya Kitaoka 120a6e
      TPointD p1 = m_vertex[index - 1];
Shinya Kitaoka 120a6e
      if (tdistance(p0, p1) > 0.1) {
Shinya Kitaoka 120a6e
        tglDrawSegment(p0, p1);
Shinya Kitaoka 120a6e
        tglDrawDisk(p0, 2 * pixelSize);
Shinya Kitaoka 120a6e
        tglDrawDisk(p1, 4 * pixelSize);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      // Disegno lo speedIn/Out corrente nel caso in cui count > 5
Shinya Kitaoka 120a6e
      if (m_speedMoved && count > 5) {
Shinya Kitaoka 120a6e
        TPointD p0 = m_vertex[count - 1];
Shinya Kitaoka 120a6e
        TPointD p1 = m_vertex[count - 2];
Shinya Kitaoka 120a6e
        TPointD p2 = m_vertex[count - 3];
Shinya Kitaoka 120a6e
        tglDrawSegment(p0, p2);
Shinya Kitaoka 120a6e
        tglDrawDisk(p0, 2 * pixelSize);
Shinya Kitaoka 120a6e
        tglDrawDisk(p1, 4 * pixelSize);
Shinya Kitaoka 120a6e
        tglDrawDisk(p2, 2 * pixelSize);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_closed)
Shinya Kitaoka 120a6e
      tglColor(TPixel32((m_color.r + 127) % 255, m_color.g,
Shinya Kitaoka 120a6e
                        (m_color.b + 127) % 255, m_color.m));
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      tglColor(m_color);
Shinya Kitaoka 120a6e
    tglDrawCircle(m_vertex[0], joinDistance * pixelSize);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MultiLinePrimitive::leftButtonDown(const TPointD &pos,
Shinya Kitaoka 120a6e
                                        const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!app) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (app->getCurrentObject()->isSpline()) {
Shinya Kitaoka 120a6e
    m_color     = TPixel32::Red;
Shinya Kitaoka 120a6e
    m_isEditing = true;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    const TColorStyle *style = app->getCurrentLevelStyle();
Shinya Kitaoka 120a6e
    if (style) {
Shinya Kitaoka 120a6e
      m_isEditing = style->isStrokeStyle();
Shinya Kitaoka 120a6e
      m_color     = style->getAverageColor();
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      m_isEditing = false;
Shinya Kitaoka 120a6e
      m_color     = TPixel32::Black;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_isEditing) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_undo = new MultilinePrimitiveUndo(m_vertex, this);
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(m_undo);
Shinya Kitaoka 120a6e
  m_mousePosition = pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Se clicco nell'ultimo vertice chiudo la linea.
Shinya Kitaoka 120a6e
  TPointD _pos       = pos;
Shinya Kitaoka 120a6e
  if (m_closed) _pos = m_vertex.front();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (e.isShiftPressed() && !m_vertex.empty())
Shinya Kitaoka 120a6e
    addVertex(rectify(m_vertex.back(), _pos));
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    addVertex(_pos);
Shinya Kitaoka 120a6e
  m_undo->setNewVertex(m_vertex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_beforeSpeedMoved = m_speedMoved;
Shinya Kitaoka 120a6e
  m_speedMoved       = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MultiLinePrimitive::leftButtonDrag(const TPointD &pos,
Shinya Kitaoka 120a6e
                                        const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  if (m_vertex.size() == 0 || m_isSingleLine) return;
Shinya Kitaoka 120a6e
  if (m_speedMoved ||
Shinya Kitaoka 120a6e
      tdistance2(m_vertex[m_vertex.size() - 1], pos) >
Shinya Kitaoka 120a6e
          sq(7.0 * m_tool->getPixelSize())) {
Shinya Kitaoka 120a6e
    moveSpeed(m_mousePosition - pos);
Shinya Kitaoka 120a6e
    m_speedMoved = true;
Shinya Kitaoka 120a6e
    m_undo->setNewVertex(m_vertex);
Shinya Kitaoka 120a6e
    m_mousePosition = pos;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MultiLinePrimitive::leftButtonDoubleClick(const TPointD &,
Shinya Kitaoka 120a6e
                                               const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  endLine();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MultiLinePrimitive::leftButtonUp(const TPointD &pos, const TMouseEvent &) {
Shinya Kitaoka 120a6e
  if (m_closed) endLine();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MultiLinePrimitive::mouseMove(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_ctrlDown = e.isCtrlPressed();
Shinya Kitaoka 120a6e
  if (m_isEditing) {
Shinya Kitaoka 120a6e
    if (e.isShiftPressed() && !m_vertex.empty())
Shinya Kitaoka 120a6e
      m_mousePosition = rectify(m_vertex.back(), pos);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      m_mousePosition = pos;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    double dist = joinDistance * joinDistance;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (!m_vertex.empty() && (tdistance2(m_mousePosition, m_vertex.front()) <
Shinya Kitaoka 120a6e
                              dist * m_tool->getPixelSize())) {
Shinya Kitaoka 120a6e
      m_closed        = true;
Shinya Kitaoka 120a6e
      m_mousePosition = m_vertex.front();
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      m_closed = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    m_mousePosition = pos;
Shinya Kitaoka 120a6e
  m_tool->invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool MultiLinePrimitive::keyDown(int key, const TPoint &point) {
Shinya Kitaoka 120a6e
  if (key != TwConsts::TK_Esc || !m_isEditing) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  UINT size = m_vertex.size();
Shinya Kitaoka 120a6e
  if (size <= 1) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_isSingleLine) TUndoManager::manager()->popUndo((size - 1) / 4 + 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_isEditing        = false;
Shinya Kitaoka 120a6e
  m_speedMoved       = false;
Shinya Kitaoka 120a6e
  m_beforeSpeedMoved = false;
Shinya Kitaoka 120a6e
  m_closed           = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_vertex.clear();
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStroke *MultiLinePrimitive::makeStroke() const {
Shinya Kitaoka 120a6e
  double thick = getThickness();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*---
Shinya Kitaoka 120a6e
   * Pencilの場合は、線幅を減らす。Thickness1の線を1ピクセルにするため。(thick
Shinya Kitaoka 120a6e
   * = 0 になる)---*/
Shinya Kitaoka 120a6e
  if (m_param->m_pencil.getValue()) thick -= 1.0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  UINT size = m_vertex.size();
Shinya Kitaoka 120a6e
  if (size <= 1) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_isSingleLine) TUndoManager::manager()->popUndo((size - 1) / 4 + 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TStroke *stroke = 0;
Shinya Kitaoka 120a6e
  std::vector<tthickpoint> points;</tthickpoint>
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < (int)size; i++) {
Shinya Kitaoka 120a6e
    TPointD vertex = m_vertex[i];
Shinya Kitaoka 120a6e
    points.push_back(TThickPoint(vertex, thick));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  stroke = new TStroke(points);
Shinya Kitaoka 120a6e
  if (m_closed) stroke->setSelfLoop();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return stroke;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MultiLinePrimitive::endLine() {
Shinya Kitaoka 120a6e
  if (!m_isEditing) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_isEditing        = false;
Shinya Kitaoka 120a6e
  m_speedMoved       = false;
Shinya Kitaoka 120a6e
  m_beforeSpeedMoved = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_isSingleLine && !m_vertex.empty() &&
Shinya Kitaoka 120a6e
      m_vertex.size() % 4 != 1 /* && !m_rasterTool*/) {
Shinya Kitaoka 120a6e
    m_vertex.erase(--m_vertex.end());
Shinya Kitaoka 120a6e
    assert(m_vertex.size() == 3 || m_vertex.size() % 4 == 1);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_tool->addStroke();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_closed) m_closed = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_vertex.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MultiLinePrimitive::onActivate() {
Shinya Kitaoka 120a6e
  m_isEditing = false;
Shinya Kitaoka 120a6e
  m_closed    = false;
Shinya Kitaoka 120a6e
  m_vertex.clear();
Shinya Kitaoka 120a6e
  m_speedMoved       = false;
Shinya Kitaoka 120a6e
  m_beforeSpeedMoved = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MultiLinePrimitive::onEnter() {
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!app) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (app->getCurrentObject()->isSpline())
Shinya Kitaoka 120a6e
    m_color = TPixel32::Red;
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    const TColorStyle *style = app->getCurrentLevelStyle();
Shinya Kitaoka 120a6e
    if (style) m_color       = style->getAverageColor();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MultiLinePrimitive::onImageChanged() { onActivate(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Line Primitive Class Implementation
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void LinePrimitive::draw() {
Shinya Kitaoka 120a6e
  UINT size = m_vertex.size();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  tglColor(TPixel32::Red);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_isEditing || m_isPrompting) {
Shinya Kitaoka 120a6e
    glBegin(GL_LINE_STRIP);
Shinya Kitaoka 120a6e
    tglVertex(m_vertex[0]);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    tglVertex(m_mousePosition);
Shinya Kitaoka 120a6e
    glEnd();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void LinePrimitive::leftButtonDown(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!app) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (app->getCurrentObject()->isSpline()) {
Shinya Kitaoka 120a6e
    m_color     = TPixel32::Red;
Shinya Kitaoka 120a6e
    m_isEditing = true;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    const TColorStyle *style = app->getCurrentLevelStyle();
Shinya Kitaoka 120a6e
    if (style) {
Shinya Kitaoka 120a6e
      m_isEditing = style->isStrokeStyle();
Shinya Kitaoka 120a6e
      m_color     = style->getAverageColor();
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      m_isEditing = false;
Shinya Kitaoka 120a6e
      m_color     = TPixel32::Black;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_isEditing) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_mousePosition = pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD _pos = pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_param->m_pencil.getValue() &&
Shinya Kitaoka 120a6e
      (m_param->m_targetType & TTool::ToonzImage ||
Shinya Kitaoka 120a6e
       m_param->m_targetType & TTool::RasterImage)) {
Shinya Kitaoka 120a6e
    if (m_param->m_rasterToolSize.getValue() % 2 != 0)
Shinya Kitaoka 120a6e
      _pos = TPointD((int)pos.x, (int)pos.y);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      _pos = TPointD((int)pos.x + 0.5, (int)pos.y + 0.5);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_vertex.size() == 0)
Shinya Kitaoka 120a6e
    addVertex(_pos);
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    if (e.isShiftPressed() && !m_vertex.empty())
Shinya Kitaoka 120a6e
      addVertex(rectify(m_vertex.back(), _pos));
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      addVertex(_pos);
Shinya Kitaoka 120a6e
    endLine();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void LinePrimitive::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  if (!m_isEditing) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_mousePosition = pos;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void LinePrimitive::leftButtonUp(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_mousePosition = pos;
Shinya Kitaoka 120a6e
  if (e.isShiftPressed() && !m_vertex.empty())
Shinya Kitaoka 120a6e
    m_vertex.push_back(rectify(m_vertex.back(), pos));
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    m_vertex.push_back(pos);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  endLine();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Ellipse Primitive Class Implementation
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EllipsePrimitive::draw() {
Shinya Kitaoka 120a6e
  if (m_isEditing || m_isPrompting ||
Shinya Kitaoka 120a6e
      areAlmostEqual(m_selectingRect.x0, m_selectingRect.x1) ||
Shinya Kitaoka 120a6e
      areAlmostEqual(m_selectingRect.y0, m_selectingRect.y1)) {
Shinya Kitaoka 120a6e
    tglColor(m_isEditing ? m_color : TPixel32::Green);
Shinya Kitaoka 120a6e
    TPointD centre = TPointD((m_selectingRect.x0 + m_selectingRect.x1) * 0.5,
Shinya Kitaoka 120a6e
                             (m_selectingRect.y0 + m_selectingRect.y1) * 0.5);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    glPushMatrix();
Shinya Kitaoka 120a6e
    tglMultMatrix(TScale(centre, m_selectingRect.x1 - m_selectingRect.x0,
Shinya Kitaoka 120a6e
                         m_selectingRect.y1 - m_selectingRect.y0));
Shinya Kitaoka 120a6e
    tglDrawCircle(centre, 0.5);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    glPopMatrix();
Shinya Kitaoka 120a6e
    drawRect(m_selectingRect, m_color, 0x5555, true);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EllipsePrimitive::leftButtonDown(const TPointD &pos, const TMouseEvent &) {
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!app) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_startPoint       = pos;
Shinya Kitaoka 120a6e
  m_selectingRect.x0 = pos.x;
Shinya Kitaoka 120a6e
  m_selectingRect.y0 = pos.y;
Shinya Kitaoka 120a6e
  m_selectingRect.x1 = pos.x;
Shinya Kitaoka 120a6e
  m_selectingRect.y1 = pos.y;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (app->getCurrentObject()->isSpline()) {
Shinya Kitaoka 120a6e
    m_isEditing = true;
Shinya Kitaoka 120a6e
    m_color     = TPixel32::Red;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    const TColorStyle *style = app->getCurrentLevelStyle();
Shinya Kitaoka 120a6e
    if (style) {
Shinya Kitaoka 120a6e
      m_isEditing = style->isStrokeStyle();
Shinya Kitaoka 120a6e
      m_color     = style->getAverageColor();
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      m_isEditing = false;
Shinya Kitaoka 120a6e
      m_color     = TPixel32::Black;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_isEditing) return;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EllipsePrimitive::leftButtonDrag(const TPointD &realPos,
Shinya Kitaoka 120a6e
                                      const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  if (!m_isEditing) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD pos;
Shinya Kitaoka 120a6e
  if (e.isShiftPressed()) {
Shinya Kitaoka 120a6e
    double distance = tdistance(realPos, m_startPoint) * M_SQRT1_2;
Shinya Kitaoka 120a6e
    pos.x           = (realPos.x > m_startPoint.x) ? m_startPoint.x + distance
Shinya Kitaoka 120a6e
                                         : m_startPoint.x - distance;
Shinya Kitaoka 120a6e
    pos.y = (realPos.y > m_startPoint.y) ? m_startPoint.y + distance
Shinya Kitaoka 120a6e
                                         : m_startPoint.y - distance;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    pos = realPos;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  m_pos = pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_selectingRect.x1 = pos.x;
Shinya Kitaoka 120a6e
  m_selectingRect.y1 = pos.y;
Shinya Kitaoka 120a6e
  if (!e.isAltPressed()) {
Shinya Kitaoka 120a6e
    m_selectingRect.x0 = m_startPoint.x;
Shinya Kitaoka 120a6e
    m_selectingRect.y0 = m_startPoint.y;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    m_selectingRect.x0 = m_startPoint.x + m_startPoint.x - pos.x;
Shinya Kitaoka 120a6e
    m_selectingRect.y0 = m_startPoint.y + m_startPoint.y - pos.y;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStroke *EllipsePrimitive::makeStroke() const {
Shinya Kitaoka 120a6e
  if (areAlmostEqual(m_selectingRect.x0, m_selectingRect.x1) ||
Shinya Kitaoka 120a6e
      areAlmostEqual(m_selectingRect.y0, m_selectingRect.y1))
Shinya Kitaoka 120a6e
    return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return makeEllipticStroke(
Shinya Kitaoka 120a6e
      getThickness(), TPointD(0.5 * (m_selectingRect.x0 + m_selectingRect.x1),
Shinya Kitaoka 120a6e
                              0.5 * (m_selectingRect.y0 + m_selectingRect.y1)),
Shinya Kitaoka 120a6e
      fabs(0.5 * (m_selectingRect.x1 - m_selectingRect.x0)),
Shinya Kitaoka 120a6e
      fabs(0.5 * (m_selectingRect.y1 - m_selectingRect.y0)));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EllipsePrimitive::leftButtonUp(const TPointD &pos, const TMouseEvent &) {
Shinya Kitaoka 120a6e
  if (!m_isEditing) return;
Shinya Kitaoka 120a6e
  m_isEditing = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_tool->addStroke();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EllipsePrimitive::mouseMove(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_pos = pos;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EllipsePrimitive::onEnter() {
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!app) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (app->getCurrentObject()->isSpline()) {
Shinya Kitaoka 120a6e
    m_color = TPixel32::Red;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    const TColorStyle *style = app->getCurrentLevelStyle();
Shinya Kitaoka 120a6e
    if (style) m_color       = style->getAverageColor();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Arc Primitive Class Implementation
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ArcPrimitive::draw() {
Shinya Kitaoka 120a6e
  switch (m_clickNumber) {
Shinya Kitaoka 120a6e
  case 1:
Shinya Kitaoka 120a6e
    tglColor(m_color);
Shinya Kitaoka 120a6e
    tglDrawSegment(m_startPoint, m_endPoint);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case 2:
Shinya Kitaoka 120a6e
    assert(m_stroke);
Shinya Kitaoka 120a6e
    if (m_stroke) {
Shinya Kitaoka 120a6e
      tglColor(m_isPrompting ? TPixel32::Green : m_color);
Shinya Kitaoka 120a6e
      if (!m_isPrompting) {
Shinya Kitaoka 120a6e
        glLineStipple(1, 0x5555);
Shinya Kitaoka 120a6e
        glEnable(GL_LINE_STIPPLE);
Shinya Kitaoka 120a6e
        glBegin(GL_LINE_STRIP);
Shinya Kitaoka 120a6e
        tglVertex(m_stroke->getControlPoint(0));
Shinya Kitaoka 120a6e
        tglVertex(m_centralPoint);
Shinya Kitaoka 120a6e
        tglVertex(m_stroke->getControlPoint(8));
Shinya Kitaoka 120a6e
        glEnd();
Shinya Kitaoka 120a6e
        glDisable(GL_LINE_STIPPLE);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      drawStrokeCenterline(*m_stroke, sqrt(tglGetPixelSize2()));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  };
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStroke *ArcPrimitive::makeStroke() const { return new TStroke(*m_stroke); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
void ArcPrimitive::leftButtonUp(const TPointD &pos, const TMouseEvent &) {
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!app) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<tthickpoint> points(9);</tthickpoint>
Shinya Kitaoka 120a6e
  double thick = getThickness();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  switch (m_clickNumber) {
Shinya Kitaoka 120a6e
  case 0:
Shinya Kitaoka 120a6e
    if (app->getCurrentObject()->isSpline()) {
Shinya Kitaoka 120a6e
      m_isEditing = true;
Shinya Kitaoka 120a6e
      m_color     = TPixel32::Red;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      const TColorStyle *style = app->getCurrentLevelStyle();
Shinya Kitaoka 120a6e
      if (style) {
Shinya Kitaoka 120a6e
        m_isEditing = style->isStrokeStyle();
Shinya Kitaoka 120a6e
        m_color     = style->getAverageColor();
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        m_isEditing = false;
Shinya Kitaoka 120a6e
        m_color     = TPixel32::Black;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!m_isEditing) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_endPoint = m_startPoint = pos;
Shinya Kitaoka 120a6e
    m_clickNumber++;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  case 1:
Shinya Kitaoka 120a6e
    points[0] = TThickPoint(m_startPoint, thick);
Shinya Kitaoka 120a6e
    points[8] = TThickPoint(pos, thick);
Shinya Kitaoka 120a6e
    points[4] = TThickPoint(0.5 * (points[0] + points[8]), thick);
Shinya Kitaoka 120a6e
    points[2] = TThickPoint(0.5 * (points[0] + points[4]), thick);
Shinya Kitaoka 120a6e
    points[6] = TThickPoint(0.5 * (points[4] + points[8]), thick);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    points[1] = TThickPoint(0.5 * (points[0] + points[2]), thick);
Shinya Kitaoka 120a6e
    points[3] = TThickPoint(0.5 * (points[2] + points[4]), thick);
Shinya Kitaoka 120a6e
    points[5] = TThickPoint(0.5 * (points[4] + points[6]), thick);
Shinya Kitaoka 120a6e
    points[7] = TThickPoint(0.5 * (points[6] + points[8]), thick);
Shinya Kitaoka 120a6e
    if (m_stroke) delete m_stroke;
Shinya Kitaoka 120a6e
    m_stroke = new TStroke(points);
Shinya Kitaoka 120a6e
    m_clickNumber++;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  case 2:
Shinya Kitaoka 120a6e
    m_tool->addStroke();
Shinya Kitaoka 120a6e
    m_stroke      = 0;
Shinya Kitaoka 120a6e
    m_clickNumber = 0;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ArcPrimitive::mouseMove(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  switch (m_clickNumber) {
Shinya Kitaoka 120a6e
  case 1:
Shinya Kitaoka 120a6e
    if (e.isShiftPressed())
Shinya Kitaoka 120a6e
      m_endPoint = rectify(m_startPoint, pos);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      m_endPoint = pos;
Shinya Kitaoka 120a6e
    m_tool->invalidate();
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case 2:
Shinya Kitaoka 120a6e
    m_centralPoint = TThickPoint(pos, getThickness());
Shinya Kitaoka 120a6e
    TThickQuadratic q(m_stroke->getControlPoint(0), m_centralPoint,
Shinya Kitaoka 120a6e
                      m_stroke->getControlPoint(8));
Shinya Kitaoka 120a6e
    TThickQuadratic q0, q1, q00, q01, q10, q11;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    q.split(0.5, q0, q1);
Shinya Kitaoka 120a6e
    q0.split(0.5, q00, q01);
Shinya Kitaoka 120a6e
    q1.split(0.5, q10, q11);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    assert(q00.getP2() == q01.getP0());
Shinya Kitaoka 120a6e
    assert(q01.getP2() == q10.getP0());
Shinya Kitaoka 120a6e
    assert(q10.getP2() == q11.getP0());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_stroke->setControlPoint(0, q00.getP0());
Shinya Kitaoka 120a6e
    m_stroke->setControlPoint(1, q00.getP1());
Shinya Kitaoka 120a6e
    m_stroke->setControlPoint(2, q00.getP2());
Shinya Kitaoka 120a6e
    m_stroke->setControlPoint(3, q01.getP1());
Shinya Kitaoka 120a6e
    m_stroke->setControlPoint(4, q01.getP2());
Shinya Kitaoka 120a6e
    m_stroke->setControlPoint(5, q10.getP1());
Shinya Kitaoka 120a6e
    m_stroke->setControlPoint(6, q10.getP2());
Shinya Kitaoka 120a6e
    m_stroke->setControlPoint(7, q11.getP1());
Shinya Kitaoka 120a6e
    m_stroke->setControlPoint(8, q11.getP2());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_tool->invalidate();
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ArcPrimitive::onEnter() {
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!app) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (app->getCurrentObject()->isSpline())
Shinya Kitaoka 120a6e
    m_color = TPixel32::Red;
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    const TColorStyle *style = app->getCurrentLevelStyle();
Shinya Kitaoka 120a6e
    if (style) m_color       = style->getAverageColor();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Polygon Primitive Class Declaration
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PolygonPrimitive::draw() {
Shinya Kitaoka 120a6e
  if (!m_isEditing && !m_isPrompting) return;
Shinya Kitaoka 120a6e
  tglColor(m_isEditing ? m_color : TPixel32::Green);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int edgeCount = m_param->m_edgeCount.getValue();
Shinya Kitaoka 120a6e
  if (edgeCount == 0) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double angleDiff = M_2PI / edgeCount;
Shinya Kitaoka 120a6e
  double angle     = (3 * M_PI + angleDiff) * 0.5;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glBegin(GL_LINE_LOOP);
Shinya Kitaoka 120a6e
  for (int i = 0; i < edgeCount; i++) {
Shinya Kitaoka 120a6e
    tglVertex(m_centre + TPointD(cos(angle) * m_radius, sin(angle) * m_radius));
Shinya Kitaoka 120a6e
    angle += angleDiff;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  glEnd();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PolygonPrimitive::leftButtonDown(const TPointD &pos, const TMouseEvent &) {
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!app) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (app->getCurrentObject()->isSpline()) {
Shinya Kitaoka 120a6e
    m_isEditing = true;
Shinya Kitaoka 120a6e
    m_color     = TPixel32::Red;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    const TColorStyle *style = app->getCurrentLevelStyle();
Shinya Kitaoka 120a6e
    if (style) {
Shinya Kitaoka 120a6e
      m_isEditing = style->isStrokeStyle();
Shinya Kitaoka 120a6e
      m_color     = style->getAverageColor();
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      m_isEditing = false;
Shinya Kitaoka 120a6e
      m_color     = TPixel32::Black;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_isEditing) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_centre = pos;
Shinya Kitaoka 120a6e
  m_radius = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PolygonPrimitive::leftButtonDrag(const TPointD &pos,
Shinya Kitaoka 120a6e
                                      const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  if (!m_isEditing) return;
Shinya Kitaoka 120a6e
  m_radius = tdistance(m_centre, pos);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStroke *PolygonPrimitive::makeStroke() const {
Shinya Kitaoka 120a6e
  double thick = getThickness();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int edgeCount = m_param->m_edgeCount.getValue();
Shinya Kitaoka 120a6e
  if (edgeCount == 0) return 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double angleDiff = M_2PI / (double)edgeCount;
Shinya Kitaoka 120a6e
  double angle     = (3 * M_PI + angleDiff) * 0.5;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TStroke *stroke = 0;
Shinya Kitaoka 120a6e
  if (m_param->m_targetType & TTool::Vectors) {
Shinya Kitaoka 120a6e
    std::vector<tthickpoint> points(4 * edgeCount + 1);</tthickpoint>
Shinya Kitaoka 120a6e
    int i;
Shinya Kitaoka 120a6e
    // Posiziono gli angoli
Shinya Kitaoka 120a6e
    for (i = 0; i <= (int)points.size(); i += 4) {
Shinya Kitaoka 120a6e
      points[i] = TThickPoint(
Shinya Kitaoka 120a6e
          m_centre + TPointD(cos(angle) * m_radius, sin(angle) * m_radius),
Shinya Kitaoka 120a6e
          thick);
Shinya Kitaoka 120a6e
      angle += angleDiff;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    // posiziono i punti medi e i punti per gestire la linearita'
Shinya Kitaoka 120a6e
    for (i = 0; i < (int)points.size() - 1; i += 4) {
Shinya Kitaoka 120a6e
      TPointD vertex           = convert(points[i]);
Shinya Kitaoka 120a6e
      TPointD nextVertex       = convert(points[i + 4]);
Shinya Kitaoka 120a6e
      TPointD speed            = computeSpeed(vertex, nextVertex, 0.01);
Shinya Kitaoka 120a6e
      TPointD speedOutPoint    = vertex + speed;
Shinya Kitaoka 120a6e
      TPointD speedInNextPoint = nextVertex - speed;
Shinya Kitaoka 120a6e
      TPointD middlePoint      = 0.5 * (speedOutPoint + speedInNextPoint);
Shinya Kitaoka 120a6e
      points[i + 1]            = TThickPoint(speedOutPoint, thick);
Shinya Kitaoka 120a6e
      points[i + 2]            = TThickPoint(middlePoint, thick);
Shinya Kitaoka 120a6e
      points[i + 3]            = TThickPoint(speedInNextPoint, thick);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    stroke = new TStroke(points);
Shinya Kitaoka 120a6e
  } else if (m_param->m_targetType & TTool::ToonzImage ||
Shinya Kitaoka 120a6e
             m_param->m_targetType & TTool::RasterImage) {
Shinya Kitaoka 120a6e
    std::vector<tthickpoint> points(edgeCount + edgeCount + 1);</tthickpoint>
Shinya Kitaoka 120a6e
    points[0] = TThickPoint(
Shinya Kitaoka 120a6e
        m_centre + TPointD(cos(angle) * m_radius, sin(angle) * m_radius),
Shinya Kitaoka 120a6e
        thick);
Shinya Kitaoka 120a6e
    for (int i = 1; i <= edgeCount; i++) {
Shinya Kitaoka 120a6e
      angle += angleDiff;
Shinya Kitaoka 120a6e
      points[i + i] = TThickPoint(
Shinya Kitaoka 120a6e
          m_centre + TPointD(cos(angle) * m_radius, sin(angle) * m_radius),
Shinya Kitaoka 120a6e
          thick);
Shinya Kitaoka 120a6e
      points[i + i - 1] = (points[i + i - 2] + points[i + i]) * 0.5;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    stroke = new TStroke(points);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  stroke->setSelfLoop();
Shinya Kitaoka 120a6e
  return stroke;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PolygonPrimitive::leftButtonUp(const TPointD &pos, const TMouseEvent &) {
Shinya Kitaoka 120a6e
  if (!m_isEditing) return;
Shinya Kitaoka 120a6e
  m_isEditing = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_tool->addStroke();
Toshihiro Shimizu 890ddd
}