Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "vectorselectiontool.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzTools includes
Toshihiro Shimizu 890ddd
#include "tools/toolhandle.h"
Toshihiro Shimizu 890ddd
#include "tools/imagegrouping.h"
Toshihiro Shimizu 890ddd
#include "tools/cursors.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzQt includes
Toshihiro Shimizu 890ddd
#include "toonzqt/selectioncommandids.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/tselectionhandle.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/imageutils.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/txsheethandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshlevelhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tobjecthandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobject.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tenv.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "drawutil.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// boost includes
Toshihiro Shimizu 890ddd
#include <boost bind.hpp=""></boost>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace ToolUtils;
Toshihiro Shimizu 890ddd
using namespace DragSelectionTool;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    Global variables
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
VectorSelectionTool l_vectorSelectionTool(TTool::Vectors);
Shinya Kitaoka 120a6e
TEnv::IntVar l_strokeSelectConstantThickness("SelectionToolConstantThickness",
Shinya Kitaoka 120a6e
                                             0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const int l_dragThreshold = 10;  //!< Distance, in pixels, the user has to
Shinya Kitaoka 120a6e
                                 //!  move from a button press to trigger a
Shinya Kitaoka 120a6e
                                 //!  selection drag.
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    Local namespace  stuff
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
FourPoints getFourPointsFromVectorImage(const TVectorImageP &img,
Shinya Kitaoka 120a6e
                                        const std::set<int> &styleIds,</int>
Shinya Kitaoka 120a6e
                                        double &maxThickness) {
Shinya Kitaoka 120a6e
  FourPoints p;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (styleIds.empty()) {
Shinya Kitaoka 120a6e
    p = img->getBBox();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    for (UINT i = 0; i < img->getStrokeCount(); i++) {
Shinya Kitaoka 120a6e
      TStroke *s = img->getStroke(i);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      for (int j = 0; j < s->getControlPointCount(); j++) {
Shinya Kitaoka 120a6e
        double thick                           = s->getControlPoint(j).thick;
Shinya Kitaoka 120a6e
        if (maxThickness < thick) maxThickness = thick;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    TRectD bbox;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    for (UINT i = 0; i < img->getStrokeCount(); i++) {
Shinya Kitaoka 120a6e
      TStroke *s = img->getStroke(i);
Shinya Kitaoka 120a6e
      if (!styleIds.count(s->getStyle())) continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      if (bbox.isEmpty())
Shinya Kitaoka 120a6e
        bbox = s->getBBox();
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        bbox += s->getBBox();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      for (int j = 0; j < s->getControlPointCount(); j++) {
Shinya Kitaoka 120a6e
        double thick                           = s->getControlPoint(j).thick;
Shinya Kitaoka 120a6e
        if (maxThickness < thick) maxThickness = thick;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    p = bbox;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return p;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool getStrokeIndexFromPos(UINT &index, const TVectorImageP &vi,
Shinya Kitaoka 120a6e
                           const TPointD &pos, double pixelSize) {
Shinya Kitaoka 120a6e
  if (!vi) return false;
Shinya Kitaoka 120a6e
  double t, dist2 = 0;
Shinya Kitaoka 120a6e
  double maxDist  = 5 * pixelSize;
Shinya Kitaoka 120a6e
  double maxDist2 = maxDist * maxDist;
Shinya Kitaoka 120a6e
  vi->getNearestStroke(pos, t, index, dist2);
Shinya Kitaoka 120a6e
  return (dist2 < maxDist2 * 4);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static bool currentOrNotSelected(const VectorSelectionTool &tool,
Shinya Kitaoka 120a6e
                                 const TFrameId &fid) {
Shinya Kitaoka 120a6e
  return (tool.getCurrentFid() == fid ||
Shinya Kitaoka 120a6e
          (tool.isSelectedFramesType() &&
Shinya Kitaoka 120a6e
           tool.getSelectedFrames().count(fid) == 0));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline void notifySelectionChanged() {
Shinya Kitaoka 120a6e
  TTool::getApplication()->getCurrentSelection()->notifySelectionChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    VectorFreeDeformer  implementation
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
VectorFreeDeformer::VectorFreeDeformer(TVectorImageP vi,
Shinya Kitaoka 120a6e
                                       std::set<int> strokeIndexes)</int>
Shinya Kitaoka 120a6e
    : FreeDeformer()
Shinya Kitaoka 120a6e
    , m_vi(vi)
Shinya Kitaoka 120a6e
    , m_strokeIndexes(strokeIndexes)
Shinya Kitaoka 120a6e
    , m_preserveThickness(false)
Shinya Kitaoka 120a6e
    , m_computeRegion(false)
Shinya Kitaoka 120a6e
    , m_flip(false) {
Shinya Kitaoka 120a6e
  TRectD r;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::set<int>::iterator it, iEnd = m_strokeIndexes.end();</int>
Shinya Kitaoka 120a6e
  for (it = m_strokeIndexes.begin(); it != iEnd; ++it) {
Shinya Kitaoka 120a6e
    TStroke *stroke = m_vi->getStroke(*it);
Shinya Kitaoka 120a6e
    r += stroke->getBBox();
Shinya Kitaoka 120a6e
    m_originalStrokes.push_back(new TStroke(*stroke));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_originalP00 = r.getP00();
Shinya Kitaoka 120a6e
  m_originalP11 = r.getP11();
Shinya Kitaoka 120a6e
  m_newPoints.push_back(m_originalP00);
Shinya Kitaoka 120a6e
  m_newPoints.push_back(r.getP10());
Shinya Kitaoka 120a6e
  m_newPoints.push_back(m_originalP11);
Shinya Kitaoka 120a6e
  m_newPoints.push_back(r.getP01());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
VectorFreeDeformer::~VectorFreeDeformer() {
Shinya Kitaoka 120a6e
  clearPointerContainer(m_originalStrokes);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorFreeDeformer::setPreserveThickness(bool preserveThickness) {
Shinya Kitaoka 120a6e
  m_preserveThickness = preserveThickness;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorFreeDeformer::setComputeRegion(bool computeRegion) {
Shinya Kitaoka 120a6e
  m_computeRegion = computeRegion;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorFreeDeformer::setFlip(bool flip) { m_flip = flip; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorFreeDeformer::setPoint(int index, const TPointD &p) {
Shinya Kitaoka 120a6e
  m_newPoints[index] = p;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorFreeDeformer::setPoints(const TPointD &p0, const TPointD &p1,
Shinya Kitaoka 120a6e
                                   const TPointD &p2, const TPointD &p3) {
Shinya Kitaoka 120a6e
  m_newPoints[0] = p0;
Shinya Kitaoka 120a6e
  m_newPoints[1] = p1;
Shinya Kitaoka 120a6e
  m_newPoints[2] = p2;
Shinya Kitaoka 120a6e
  m_newPoints[3] = p3;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorFreeDeformer::deformRegions() {
Shinya Kitaoka 120a6e
  if (m_strokeIndexes.empty() || !m_computeRegion) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::vector<int> selectedIndexes(m_strokeIndexes.begin(),</int>
Shinya Kitaoka 120a6e
                                   m_strokeIndexes.end());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_vi->notifyChangedStrokes(selectedIndexes, m_originalStrokes, m_flip);
Shinya Kitaoka 120a6e
  m_computeRegion = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorFreeDeformer::deformImage() {
Shinya Kitaoka 120a6e
  // debug
Shinya Kitaoka 120a6e
  assert(m_strokeIndexes.size() == m_originalStrokes.size());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // release
Shinya Kitaoka 120a6e
  if (m_strokeIndexes.size() != m_originalStrokes.size()) {
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QMutexLocker lock(m_vi->getMutex());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::size_t i = 0;
Shinya Kitaoka 120a6e
  for (auto it = m_strokeIndexes.begin(), end = m_strokeIndexes.end();
Shinya Kitaoka 120a6e
       it != end; ++it) {
Shinya Kitaoka 120a6e
    TStroke *stroke         = m_vi->getStroke(*it);
Shinya Kitaoka 120a6e
    TStroke *originalStroke = m_originalStrokes[i++];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    assert(stroke->getControlPointCount() ==
Shinya Kitaoka 120a6e
           originalStroke->getControlPointCount());
Shinya Kitaoka 120a6e
    for (int j = 0, count = stroke->getControlPointCount(); j < count; ++j) {
Shinya Kitaoka 120a6e
      TThickPoint p = deform(originalStroke->getControlPoint(j));
Shinya Kitaoka 120a6e
      stroke->setControlPoint(j, p);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_computeRegion) deformRegions();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TThickPoint VectorFreeDeformer::deform(TThickPoint point) {
Shinya Kitaoka 120a6e
  double vs  = m_originalP11.x - m_originalP00.x;
Shinya Kitaoka 120a6e
  double s   = (vs == 0) ? 0 : (point.x - m_originalP00.x) / vs;
Shinya Kitaoka 120a6e
  double vt  = m_originalP11.y - m_originalP00.y;
Shinya Kitaoka 120a6e
  double t   = (vt == 0) ? 0 : (point.y - m_originalP00.y) / vt;
Shinya Kitaoka 120a6e
  TPointD A  = m_newPoints[0];
Shinya Kitaoka 120a6e
  TPointD B  = m_newPoints[1];
Shinya Kitaoka 120a6e
  TPointD C  = m_newPoints[2];
Shinya Kitaoka 120a6e
  TPointD D  = m_newPoints[3];
Shinya Kitaoka 120a6e
  TPointD AD = (1 - t) * A + t * D;
Shinya Kitaoka 120a6e
  TPointD BC = (1 - t) * B + t * C;
Shinya Kitaoka 120a6e
  TPointD p  = (1 - s) * AD + s * BC;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double thickness = point.thick;
Shinya Kitaoka 120a6e
  if (!m_preserveThickness) {
Shinya Kitaoka 120a6e
    double eps          = 1.e-2;
Shinya Kitaoka 120a6e
    TPointD p0x         = TPointD(p.x - eps, p.x);
Shinya Kitaoka 120a6e
    TPointD p1x         = TPointD(p.x + eps, p.x);
Shinya Kitaoka 120a6e
    TPointD p0y         = TPointD(p.x, p.y - eps);
Shinya Kitaoka 120a6e
    TPointD p1y         = TPointD(p.x, p.y + eps);
Shinya Kitaoka 120a6e
    m_preserveThickness = true;
Shinya Kitaoka 120a6e
    TThickPoint newp0x  = deform(p0x);
Shinya Kitaoka 120a6e
    TThickPoint newp1x  = deform(p1x);
Shinya Kitaoka 120a6e
    TThickPoint newp0y  = deform(p0y);
Shinya Kitaoka 120a6e
    TThickPoint newp1y  = deform(p1y);
Shinya Kitaoka 120a6e
    m_preserveThickness = false;
Shinya Kitaoka 120a6e
    double newA         = fabs(cross(newp1x - newp0x, newp1y - newp0y));
Shinya Kitaoka 120a6e
    double a            = 4 * eps * eps;
Shinya Kitaoka 120a6e
    thickness *= sqrt(newA / a);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return TThickPoint(p, thickness);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    UndoChangeStrokes  implementation
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DragSelectionTool::UndoChangeStrokes::UndoChangeStrokes(
Shinya Kitaoka 120a6e
    TXshSimpleLevel *level, const TFrameId &frameId, VectorSelectionTool *tool,
Shinya Kitaoka 120a6e
    const StrokeSelection &selection)
Shinya Kitaoka 120a6e
    : ToolUtils::TToolUndo(level, frameId)
Shinya Kitaoka 120a6e
    , m_tool(tool)
Shinya Kitaoka 120a6e
    , m_selectionCount(tool->getSelectionCount())  // Not related to selection
Shinya Kitaoka 120a6e
    , m_oldBBox(tool->getBBox())
Shinya Kitaoka 120a6e
    , m_oldCenter(tool->getCenter())
Shinya Kitaoka 120a6e
    , m_oldDeformValues(tool->m_deformValues)
Shinya Kitaoka 120a6e
    , m_newDeformValues()
Shinya Kitaoka 120a6e
    , m_flip(false) {
Shinya Kitaoka 120a6e
  TVectorImageP vi = m_level->getFrame(m_frameId, false);
Shinya Kitaoka 120a6e
  if (!vi) {
Shinya Kitaoka 120a6e
    assert(vi);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const StrokeSelection::IndexesContainer &indexes = selection.getSelection();
Shinya Kitaoka 120a6e
  m_indexes.assign(indexes.begin(), indexes.end());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  registerStrokes(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DragSelectionTool::UndoChangeStrokes::UndoChangeStrokes(
Shinya Kitaoka 120a6e
    TXshSimpleLevel *level, const TFrameId &frameId, VectorSelectionTool *tool,
Shinya Kitaoka 120a6e
    const LevelSelection &selection)
Shinya Kitaoka 120a6e
    : ToolUtils::TToolUndo(level, frameId)
Shinya Kitaoka 120a6e
    , m_tool(tool)
Shinya Kitaoka 120a6e
    , m_selectionCount(tool->getSelectionCount())  // Not related to selection
Shinya Kitaoka 120a6e
    , m_oldBBox(tool->getBBox())
Shinya Kitaoka 120a6e
    , m_oldCenter(tool->getCenter())
Shinya Kitaoka 120a6e
    , m_oldDeformValues(tool->m_deformValues)
Shinya Kitaoka 120a6e
    , m_newDeformValues()
Shinya Kitaoka 120a6e
    , m_flip(false) {
Shinya Kitaoka 120a6e
  TVectorImageP vi = m_level->getFrame(m_frameId, false);
Shinya Kitaoka 120a6e
  if (!vi) {
Shinya Kitaoka 120a6e
    assert(vi);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_indexes = getSelectedStrokes(*vi, selection);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  registerStrokes(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DragSelectionTool::UndoChangeStrokes::~UndoChangeStrokes() {
Shinya Kitaoka 120a6e
  clearPointerContainer(m_oldStrokes);
Shinya Kitaoka 120a6e
  clearPointerContainer(m_newStrokes);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::UndoChangeStrokes::registerStrokes(bool beforeModify) {
Shinya Kitaoka 120a6e
  TVectorImageP vi = m_level->getFrame(m_frameId, false);
Shinya Kitaoka 120a6e
  if (!vi) {
Shinya Kitaoka 120a6e
    assert(vi);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::vector<tstroke *=""> &strokes = beforeModify ? m_oldStrokes : m_newStrokes;</tstroke>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRectD bbox;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int s, sCount = int(m_indexes.size());
Shinya Kitaoka 120a6e
  for (s = 0; s != sCount; ++s) {
Shinya Kitaoka 120a6e
    TStroke *stroke = vi->getStroke(m_indexes[s]);
Shinya Kitaoka 120a6e
    bbox += stroke->getBBox();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    strokes.push_back(new TStroke(*stroke));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (beforeModify && !bbox.isEmpty()) {
Shinya Kitaoka 120a6e
    ImageUtils::getFillingInformationOverlappingArea(vi, m_regionsData, bbox);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    m_newBBox         = m_tool->getBBox();
Shinya Kitaoka 120a6e
    m_newCenter       = m_tool->getCenter();
Shinya Kitaoka 120a6e
    m_newDeformValues = m_tool->m_deformValues;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::UndoChangeStrokes::transform(
Shinya Kitaoka 120a6e
    const std::vector<tstroke *=""> &strokes, FourPoints bbox, TPointD center,</tstroke>
Shinya Kitaoka 120a6e
    DragSelectionTool::DeformValues deformValues) const {
Shinya Kitaoka 120a6e
  TVectorImageP image = m_level->getFrame(m_frameId, true);
Shinya Kitaoka 120a6e
  if (!image) {
Shinya Kitaoka 120a6e
    assert(image);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int s, sCount = int(m_indexes.size());
Shinya Kitaoka 120a6e
  for (s = 0; s != sCount; ++s) {
Shinya Kitaoka 120a6e
    int index = m_indexes[s];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TStroke *sourcesStroke = strokes[s], *stroke = image->getStroke(index);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    int cp, cpCount = stroke->getControlPointCount();
Shinya Kitaoka 120a6e
    for (cp = 0; cp != cpCount; ++cp)
Shinya Kitaoka 120a6e
      stroke->setControlPoint(cp, sourcesStroke->getControlPoint(cp));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  image->notifyChangedStrokes(m_indexes, strokes, m_flip);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_tool->isSelectionEmpty() &&
Shinya Kitaoka 120a6e
      m_selectionCount == m_tool->getSelectionCount()) {
Shinya Kitaoka 120a6e
    m_tool->setBBox(bbox);
Shinya Kitaoka 120a6e
    m_tool->setCenter(center);
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    m_tool->computeBBox();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_tool->notifyImageChanged(m_frameId);
Shinya Kitaoka 120a6e
  m_tool->m_deformValues = deformValues;
Shinya Kitaoka 120a6e
  TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::UndoChangeStrokes::restoreRegions() const {
Shinya Kitaoka 120a6e
  TVectorImageP vi = m_level->getFrame(m_frameId, true);
Shinya Kitaoka 120a6e
  if (!vi) {
Shinya Kitaoka 120a6e
    assert(vi);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ImageUtils::assignFillingInformation(*vi, m_regionsData);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::UndoChangeStrokes::undo() const {
Shinya Kitaoka 120a6e
  transform(m_oldStrokes, m_oldBBox, m_oldCenter, m_oldDeformValues);
Shinya Kitaoka 120a6e
  restoreRegions();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::UndoChangeStrokes::redo() const {
Shinya Kitaoka 120a6e
  transform(m_newStrokes, m_newBBox, m_newCenter, m_newDeformValues);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int DragSelectionTool::UndoChangeStrokes::getSize() const {
Shinya Kitaoka 120a6e
  return sizeof(*this) + sizeof(*m_tool);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// UndoChangeOutlineStyle
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class UndoChangeOutlineStyle final : public ToolUtils::TToolUndo {
Shinya Kitaoka 120a6e
  std::vector<tstroke::outlineoptions> m_oldOptions, m_newOptions;</tstroke::outlineoptions>
Shinya Kitaoka 120a6e
  FourPoints m_oldBBox, m_newBBox;
Shinya Kitaoka 120a6e
  VectorSelectionTool *m_tool;
Shinya Kitaoka 120a6e
  std::vector<int> m_indexes;</int>
Shinya Kitaoka 120a6e
  int m_selectionCount;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  UndoChangeOutlineStyle(TXshSimpleLevel *level, const TFrameId &frameId,
Shinya Kitaoka 120a6e
                         VectorSelectionTool *tool);
Shinya Kitaoka 120a6e
  ~UndoChangeOutlineStyle() {}
Shinya Kitaoka 120a6e
  void registerStrokes(bool beforeModify = false);
Shinya Kitaoka 120a6e
  void transform(const std::vector<tstroke::outlineoptions> &options,</tstroke::outlineoptions>
Shinya Kitaoka 120a6e
                 FourPoints bbox) const;
Shinya Kitaoka 473e70
  void undo() const override;
Shinya Kitaoka 473e70
  void redo() const override;
Shinya Kitaoka 473e70
  int getSize() const override;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
UndoChangeOutlineStyle::UndoChangeOutlineStyle(TXshSimpleLevel *level,
Shinya Kitaoka 120a6e
                                               const TFrameId &frameId,
Shinya Kitaoka 120a6e
                                               VectorSelectionTool *tool)
Shinya Kitaoka 120a6e
    : ToolUtils::TToolUndo(level, frameId)
Shinya Kitaoka 120a6e
    , m_tool(tool)
Shinya Kitaoka 120a6e
    , m_oldBBox(tool->getBBox())
Shinya Kitaoka 120a6e
    , m_selectionCount(tool->getSelectionCount()) {
Shinya Kitaoka 120a6e
  TVectorImageP image = m_level->getFrame(m_frameId, false);
Shinya Kitaoka 120a6e
  assert(!!image);
Shinya Kitaoka 120a6e
  if (!image) return;
Shinya Kitaoka 120a6e
  StrokeSelection *strokeSelection =
Shinya Kitaoka 120a6e
      dynamic_cast<strokeselection *="">(tool->getSelection());</strokeselection>
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < (int)image->getStrokeCount(); i++) {
Shinya Kitaoka 120a6e
    if (!strokeSelection->isSelected(i) && !m_tool->isLevelType() &&
Shinya Kitaoka 120a6e
        !m_tool->isSelectedFramesType())
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    m_indexes.push_back(i);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  registerStrokes(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void UndoChangeOutlineStyle::registerStrokes(bool beforeModify) {
Shinya Kitaoka 120a6e
  TVectorImageP image = m_level->getFrame(m_frameId, false);
Shinya Kitaoka 120a6e
  assert(!!image);
Shinya Kitaoka 120a6e
  if (!image) return;
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < (int)m_indexes.size(); i++) {
Shinya Kitaoka 120a6e
    if (beforeModify)
Shinya Kitaoka 120a6e
      m_oldOptions.push_back(image->getStroke(m_indexes[i])->outlineOptions());
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      m_newOptions.push_back(image->getStroke(m_indexes[i])->outlineOptions());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (!beforeModify) m_newBBox = m_tool->getBBox();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void UndoChangeOutlineStyle::transform(
Shinya Kitaoka 120a6e
    const std::vector<tstroke::outlineoptions> &options,</tstroke::outlineoptions>
Shinya Kitaoka 120a6e
    FourPoints bbox) const {
Shinya Kitaoka 120a6e
  TVectorImageP image = m_level->getFrame(m_frameId, true);
Shinya Kitaoka 120a6e
  assert(!!image);
Shinya Kitaoka 120a6e
  if (!image) return;
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < (int)m_indexes.size(); i++) {
Shinya Kitaoka 120a6e
    int index                                 = m_indexes[i];
Shinya Kitaoka 120a6e
    image->getStroke(index)->outlineOptions() = options[i];
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (!m_tool->isSelectionEmpty() &&
Shinya Kitaoka 120a6e
      m_selectionCount == m_tool->getSelectionCount())
Shinya Kitaoka 120a6e
    m_tool->setBBox(bbox);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    m_tool->computeBBox();
Shinya Kitaoka 120a6e
  m_tool->notifyImageChanged(m_frameId);
Shinya Kitaoka 120a6e
  TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void UndoChangeOutlineStyle::undo() const {
Shinya Kitaoka 120a6e
  transform(m_oldOptions, m_oldBBox);
Shinya Kitaoka 120a6e
  TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void UndoChangeOutlineStyle::redo() const {
Shinya Kitaoka 120a6e
  transform(m_newOptions, m_newBBox);
Shinya Kitaoka 120a6e
  TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
int UndoChangeOutlineStyle::getSize() const {
Shinya Kitaoka 120a6e
  // NOTE: This is definitely wrong... sizeof(vector) DOES NOT correspond to its
Shinya Kitaoka 120a6e
  // actual size - as it is internally allocated with new!!
Shinya Kitaoka 120a6e
  return sizeof(*this) + sizeof(*m_tool);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// VectorDeformTool::VFDScopedBlock
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
struct VectorDeformTool::VFDScopedBlock  //! Type bounding the scope of free
Shinya Kitaoka 120a6e
                                         //! deformers in the tool.
Shinya Kitaoka 120a6e
{
Shinya Kitaoka 120a6e
  VFDScopedBlock(SelectionTool *tool) : m_tool(tool) {
Shinya Kitaoka 120a6e
    m_tool->setNewFreeDeformer();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  ~VFDScopedBlock() { m_tool->clearDeformers(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  SelectionTool *m_tool;  //!< [\p external]  Tool owning the deformers.
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// VectorDeformTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DragSelectionTool::VectorDeformTool::VectorDeformTool(VectorSelectionTool *tool)
Shinya Kitaoka 120a6e
    : DeformTool(tool), m_undo() {
Shinya Kitaoka 120a6e
  if (!TTool::getApplication()->getCurrentObject()->isSpline()) {
Shinya Kitaoka 120a6e
    m_undo.reset(new UndoChangeStrokes(
Shinya Kitaoka 120a6e
        TTool::getApplication()->getCurrentLevel()->getSimpleLevel(),
Shinya Kitaoka 120a6e
        tool->getCurrentFid(), tool, tool->strokeSelection()));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DragSelectionTool::VectorDeformTool::~VectorDeformTool() {
Shinya Kitaoka 120a6e
  // DO NOT REMOVE - DESTRUCTS TYPES INCOMPLETE IN THE HEADER
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorDeformTool::applyTransform(FourPoints bbox) {
Shinya Kitaoka 120a6e
  SelectionTool *tool = getTool();
Toshihiro Shimizu 890ddd
otakuto e28b5e
  std::unique_ptr<vfdscopedblock> localVfdScopedBlock;</vfdscopedblock>
otakuto e28b5e
  if (!m_vfdScopedBlock) {
otakuto e28b5e
    std::unique_ptr<vfdscopedblock> &vfdScopedBlock =</vfdscopedblock>
Shinya Kitaoka 120a6e
        m_isDragging ? m_vfdScopedBlock : localVfdScopedBlock;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    vfdScopedBlock.reset(new VFDScopedBlock(tool));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  VectorFreeDeformer *freeDeformer =
Shinya Kitaoka 120a6e
      static_cast<vectorfreedeformer *="">(tool->getFreeDeformer());</vectorfreedeformer>
Shinya Kitaoka 120a6e
  freeDeformer->setPoints(bbox.getP00(), bbox.getP10(), bbox.getP11(),
Shinya Kitaoka 120a6e
                          bbox.getP01());
Shinya Kitaoka 120a6e
  freeDeformer->setComputeRegion(!m_isDragging);
Shinya Kitaoka 120a6e
  freeDeformer->setPreserveThickness(tool->isConstantThickness());
Shinya Kitaoka 120a6e
  freeDeformer->setFlip(isFlip());
Toshihiro Shimizu 890ddd
otakuto e28b5e
  if (!TTool::getApplication()->getCurrentObject()->isSpline() && m_undo)
Shinya Kitaoka 120a6e
    m_undo->setFlip(isFlip());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  freeDeformer->deformImage();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  tool->invalidate();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_isDragging) tool->notifyImageChanged();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  tool->m_deformValues.m_isSelectionModified = true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_isDragging && (tool->isLevelType() || tool->isSelectedFramesType()))
Shinya Kitaoka 120a6e
    transformWholeLevel();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorDeformTool::addTransformUndo() {
Shinya Kitaoka 120a6e
  if (TTool::getApplication()->getCurrentObject()->isSpline())
Shinya Kitaoka 120a6e
    TUndoManager::manager()->add(
Shinya Kitaoka 120a6e
        new UndoPath(getTool()
Shinya Kitaoka 120a6e
                         ->getXsheet()
Shinya Kitaoka 120a6e
                         ->getStageObject(getTool()->getObjectId())
Shinya Kitaoka 120a6e
                         ->getSpline()));
otakuto e28b5e
  else if (m_undo) {
Shinya Kitaoka 120a6e
    m_undo->registerStrokes();
Shinya Kitaoka 120a6e
    TUndoManager::manager()->add(m_undo.release());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorDeformTool::transformWholeLevel() {
Shinya Kitaoka 120a6e
  VectorSelectionTool *tool = dynamic_cast<vectorselectiontool *="">(m_tool);</vectorselectiontool>
Shinya Kitaoka 120a6e
  assert(tool);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(!tool->levelSelection().isEmpty());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshSimpleLevel *level =
Shinya Kitaoka 120a6e
      TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::vector<tframeid> fids;</tframeid>
Shinya Kitaoka 120a6e
  level->getFids(fids);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Remove unwanted fids
Shinya Kitaoka 120a6e
  fids.erase(std::remove_if(
Shinya Kitaoka 120a6e
                 fids.begin(), fids.end(),
Shinya Kitaoka 120a6e
                 boost::bind(::currentOrNotSelected, boost::cref(*tool), _1)),
Shinya Kitaoka 120a6e
             fids.end());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TUndoManager::manager()->beginBlock();
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    addTransformUndo();  // For current frame
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    int f, fCount = int(fids.size());
Shinya Kitaoka 120a6e
    for (f = 0; f != fCount; ++f) {
Shinya Kitaoka 120a6e
      const TFrameId &fid = fids[f];
Shinya Kitaoka 120a6e
      int t               = f + 1;  // Current frame's data is always at index 0
Shinya Kitaoka 120a6e
                                    // The others are thus shifted by 1
Shinya Kitaoka 120a6e
      // Skip nonselected frames
Shinya Kitaoka 120a6e
      if (tool->getCurrentFid() == fid ||
Shinya Kitaoka 120a6e
          (tool->isSelectedFramesType() &&
Shinya Kitaoka 120a6e
           tool->getSelectedFrames().count(fid) == 0))
Shinya Kitaoka 120a6e
        continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      TVectorImageP vi = level->getFrame(fid, true);
Shinya Kitaoka 120a6e
      if (!vi) continue;
Toshihiro Shimizu 890ddd
otakuto e28b5e
      std::unique_ptr<undochangestrokes> undo(</undochangestrokes>
Shinya Kitaoka 120a6e
          new UndoChangeStrokes(level, fid, tool, tool->levelSelection()));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      std::set<int> strokesIndices;</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      for (int s = 0; s < (int)vi->getStrokeCount(); ++s)
Shinya Kitaoka 120a6e
        strokesIndices.insert(s);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      FourPoints bbox = tool->getBBox(t);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      VectorFreeDeformer *freeDeformer =
Shinya Kitaoka 120a6e
          static_cast<vectorfreedeformer *="">(tool->getFreeDeformer(t));</vectorfreedeformer>
Shinya Kitaoka 120a6e
      freeDeformer->setPoints(bbox.getPoint(0), bbox.getPoint(1),
Shinya Kitaoka 120a6e
                              bbox.getPoint(2), bbox.getPoint(3));
Shinya Kitaoka 120a6e
      freeDeformer->setComputeRegion(true);
Shinya Kitaoka 120a6e
      freeDeformer->setPreserveThickness(tool->isConstantThickness());
Shinya Kitaoka 120a6e
      freeDeformer->setFlip(isFlip());
Shinya Kitaoka 120a6e
      freeDeformer->deformImage();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      undo->registerStrokes();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      TUndoManager::manager()->add(undo.release());
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TUndoManager::manager()->endBlock();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Finally, notify changed frames
Shinya Kitaoka 120a6e
  std::for_each(fids.begin(), fids.end(),
Shinya Kitaoka 120a6e
                boost::bind(  // NOTE: current frame is not here - it should be,
Shinya Kitaoka 120a6e
                    &TTool::notifyImageChanged, m_tool,
Shinya Kitaoka 120a6e
                    _1));  //       but it's currently unnecessary, in fact...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // notifyImageChanged(fid) must be invoked OUTSIDE of the loop - since it
Shinya Kitaoka 120a6e
  // seems to imply notifyImageChanged()
Shinya Kitaoka 120a6e
  // on CURRENT image - which seems wrong, but it's too low-level and I'm not
Shinya Kitaoka 120a6e
  // changing it.
Shinya Kitaoka 120a6e
  // This reasonably leads to computeBBox(), but bboxes are taken as INPUT to
Shinya Kitaoka 120a6e
  // this transformation...            >:(
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool DragSelectionTool::VectorDeformTool::isFlip() {
Shinya Kitaoka 120a6e
  TPointD scaleValue = getTool()->m_deformValues.m_scaleValue;
Shinya Kitaoka 120a6e
  return m_startScaleValue.x * scaleValue.x < 0 ||
Shinya Kitaoka 120a6e
         m_startScaleValue.y * scaleValue.y < 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorDeformTool::leftButtonUp(const TPointD &pos,
Shinya Kitaoka 120a6e
                                                       const TMouseEvent &e) {
otakuto e28b5e
  std::unique_ptr<vfdscopedblock> vfdScopedBlock(std::move(m_vfdScopedBlock));</vfdscopedblock>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SelectionTool *tool = getTool();
Shinya Kitaoka 120a6e
  VectorFreeDeformer *deformer =
Shinya Kitaoka 120a6e
      dynamic_cast<vectorfreedeformer *="">(tool->getFreeDeformer());</vectorfreedeformer>
Shinya Kitaoka 120a6e
  if (!deformer) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  deformer->setComputeRegion(true);
Shinya Kitaoka 120a6e
  deformer->setFlip(isFlip());
Shinya Kitaoka 120a6e
  deformer->deformRegions();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!tool->isLevelType() && !tool->isSelectedFramesType())
Shinya Kitaoka 120a6e
    addTransformUndo();
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    transformWholeLevel();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_isDragging = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  tool->notifyImageChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// VectorRotationTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DragSelectionTool::VectorRotationTool::VectorRotationTool(
Shinya Kitaoka 120a6e
    VectorSelectionTool *tool)
Shinya Kitaoka 120a6e
    : VectorDeformTool(tool), m_rotation(new Rotation(this)) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorRotationTool::transform(TAffine aff,
Shinya Kitaoka 120a6e
                                                      double angle) {
Shinya Kitaoka 120a6e
  SelectionTool *tool = getTool();
Shinya Kitaoka 120a6e
  FourPoints newBbox(tool->getBBox() * aff);
Shinya Kitaoka 120a6e
  TPointD center = m_rotation->getStartCenter();
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < tool->getBBoxsCount(); i++) {
Shinya Kitaoka 120a6e
    aff = TRotation(center, angle);
Shinya Kitaoka 120a6e
    tool->setBBox(tool->getBBox(i) * aff, i);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  applyTransform(newBbox);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorRotationTool::leftButtonDrag(
Shinya Kitaoka 120a6e
    const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_rotation->leftButtonDrag(pos, e);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorRotationTool::draw() { m_rotation->draw(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// VectorFreeDeformTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DragSelectionTool::VectorFreeDeformTool::VectorFreeDeformTool(
Shinya Kitaoka 120a6e
    VectorSelectionTool *tool)
Shinya Kitaoka 120a6e
    : VectorDeformTool(tool), m_freeDeform(new FreeDeform(this)) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorFreeDeformTool::leftButtonDrag(
Shinya Kitaoka 120a6e
    const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_freeDeform->leftButtonDrag(pos, e);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// VectorMoveSelectionTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DragSelectionTool::VectorMoveSelectionTool::VectorMoveSelectionTool(
Shinya Kitaoka 120a6e
    VectorSelectionTool *tool)
Shinya Kitaoka 120a6e
    : VectorDeformTool(tool), m_moveSelection(new MoveSelection(this)) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorMoveSelectionTool::transform(TAffine aff) {
Shinya Kitaoka 120a6e
  SelectionTool *tool = getTool();
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < (int)tool->getBBoxsCount(); i++)
Shinya Kitaoka 120a6e
    tool->setBBox(tool->getBBox(i) * aff, i);
Shinya Kitaoka 120a6e
  getTool()->setCenter(aff * tool->getCenter());
shun-iwasawa 7f1e30
  applyTransform(tool->getBBox());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorMoveSelectionTool::leftButtonDown(
Shinya Kitaoka 120a6e
    const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_moveSelection->leftButtonDown(pos, e);
Shinya Kitaoka 120a6e
  VectorDeformTool::leftButtonDown(pos, e);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorMoveSelectionTool::leftButtonDrag(
Shinya Kitaoka 120a6e
    const TPointD &pos, const TMouseEvent &e) {
shun-iwasawa 7f1e30
  if (e.isCtrlPressed() ||
shun-iwasawa 7f1e30
      norm2(pos - getStartPos()) > l_dragThreshold * getTool()->getPixelSize())
Shinya Kitaoka 120a6e
    m_moveSelection->leftButtonDrag(pos, e);
shun-iwasawa 7f1e30
  else  // snap to the original position
shun-iwasawa 7f1e30
    m_moveSelection->leftButtonDrag(getStartPos(), e);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// VectorScaleTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DragSelectionTool::VectorScaleTool::VectorScaleTool(VectorSelectionTool *tool,
Shinya Kitaoka 120a6e
                                                    int type)
Shinya Kitaoka 120a6e
    : VectorDeformTool(tool), m_scale(new Scale(this, type)) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
TPointD DragSelectionTool::VectorScaleTool::transform(int index,
Shinya Kitaoka 120a6e
                                                      TPointD newPos) {
Shinya Kitaoka 120a6e
  SelectionTool *tool = getTool();
Shinya Kitaoka 120a6e
  TPointD scaleValue  = tool->m_deformValues.m_scaleValue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<fourpoints> startBboxs = m_scale->getStartBboxs();</fourpoints>
Shinya Kitaoka 120a6e
  TPointD center                     = m_scale->getStartCenter();
Shinya Kitaoka 120a6e
  FourPoints bbox = m_scale->bboxScaleInCenter(index, startBboxs[0], newPos,
Shinya Kitaoka 120a6e
                                               scaleValue, center, true);
Shinya Kitaoka 120a6e
  if (bbox == startBboxs[0]) return scaleValue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool scaleInCenter = m_scale->scaleInCenter();
Shinya Kitaoka 120a6e
  // Se non ho scalato rispetto al centro calcolo la posizione del nuovo centro
Shinya Kitaoka 120a6e
  if (!scaleInCenter)
Shinya Kitaoka 120a6e
    tool->setCenter(m_scale->getNewCenter(index, startBboxs[0], scaleValue));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (tool->isLevelType() || tool->isSelectedFramesType()) {
Shinya Kitaoka 120a6e
    int i;
Shinya Kitaoka 120a6e
    for (i = 1; i < (int)tool->getBBoxsCount(); i++) {
Shinya Kitaoka 120a6e
      FourPoints oldBbox = startBboxs[i];
Shinya Kitaoka 120a6e
      TPointD frameCenter =
Shinya Kitaoka 120a6e
          scaleInCenter ? center
MCCCS a0ce32
                        : oldBbox.getPoint(getSymmetricPointIndex(index));
Shinya Kitaoka 120a6e
      TPointD newp =
Shinya Kitaoka 120a6e
          m_scale->getScaledPoint(index, oldBbox, scaleValue, frameCenter);
Shinya Kitaoka 120a6e
      FourPoints newBbox = m_scale->bboxScaleInCenter(
Shinya Kitaoka 120a6e
          index, oldBbox, newp, scaleValue, frameCenter, false);
Shinya Kitaoka 120a6e
      tool->setBBox(newBbox, i);
Shinya Kitaoka 120a6e
      if (!scaleInCenter)
Shinya Kitaoka 120a6e
        tool->setCenter(m_scale->getNewCenter(index, oldBbox, scaleValue), i);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  tool->setBBox(bbox);
Shinya Kitaoka 120a6e
  applyTransform(bbox);
Shinya Kitaoka 120a6e
  return scaleValue;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorScaleTool::leftButtonDown(const TPointD &pos,
Shinya Kitaoka 120a6e
                                                        const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_scale->leftButtonDown(pos, e);
Shinya Kitaoka 120a6e
  VectorDeformTool::leftButtonDown(pos, e);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorScaleTool::leftButtonDrag(const TPointD &pos,
Shinya Kitaoka 120a6e
                                                        const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_scale->leftButtonDrag(pos, e);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// VectorChangeThicknessTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DragSelectionTool::VectorChangeThicknessTool::VectorChangeThicknessTool(
Shinya Kitaoka 120a6e
    VectorSelectionTool *tool)
Shinya Kitaoka 120a6e
    : DragTool(tool), m_curPos(), m_firstPos(), m_thicknessChange(0) {
Shinya Kitaoka 120a6e
  TVectorImageP vi = tool->getImage(false);
Shinya Kitaoka 120a6e
  assert(vi);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  setStrokesThickness(*vi);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshSimpleLevel *level =
Shinya Kitaoka 120a6e
      TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Shinya Kitaoka 120a6e
  m_undo.reset(new UndoChangeStrokes(level, tool->getCurrentFid(), tool,
Shinya Kitaoka 120a6e
                                     tool->strokeSelection()));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
VectorChangeThicknessTool::~VectorChangeThicknessTool() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
namespace SetStrokeThickness {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace DragSelectionTool;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct Data {
Shinya Kitaoka 120a6e
  VectorChangeThicknessTool &m_tool;
Shinya Kitaoka 120a6e
  const TVectorImage &m_vi;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
}  // setStrokeThickness
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorChangeThicknessTool::setStrokesThickness(
Shinya Kitaoka 120a6e
    TVectorImage &vi) {
Shinya Kitaoka 120a6e
  struct locals {
Shinya Kitaoka 120a6e
    static void setThickness(const SetStrokeThickness::Data &data, int s) {
Shinya Kitaoka 120a6e
      const TStroke &stroke = *data.m_vi.getStroke(s);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      std::vector<double> strokeThickness;</double>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      int cp, cpCount = stroke.getControlPointCount();
Shinya Kitaoka 120a6e
      strokeThickness.reserve(cpCount);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      for (cp = 0; cp != cpCount; ++cp)
Shinya Kitaoka 120a6e
        strokeThickness.push_back(stroke.getControlPoint(cp).thick);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      data.m_tool.m_strokesThickness[s] = strokeThickness;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  };  // locals
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SetStrokeThickness::Data data = {*this, vi};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  VectorSelectionTool *vsTool = static_cast<vectorselectiontool *="">(m_tool);</vectorselectiontool>
Shinya Kitaoka 120a6e
  const LevelSelection &levelSelection = vsTool->levelSelection();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (levelSelection.isEmpty()) {
Shinya Kitaoka 120a6e
    StrokeSelection *strokeSelection =
Shinya Kitaoka 120a6e
        static_cast<strokeselection *="">(m_tool->getSelection());</strokeselection>
Shinya Kitaoka 120a6e
    const std::set<int> &selectedStrokeIdxs = strokeSelection->getSelection();</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    std::for_each(selectedStrokeIdxs.begin(), selectedStrokeIdxs.end(),
Shinya Kitaoka 120a6e
                  boost::bind(locals::setThickness, boost::cref(data), _1));
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    std::vector<int> strokeIdxs = getSelectedStrokes(vi, levelSelection);</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    std::for_each(strokeIdxs.begin(), strokeIdxs.end(),
Shinya Kitaoka 120a6e
                  boost::bind(locals::setThickness, boost::cref(data), _1));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
namespace ChangeImageThickness {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace DragSelectionTool;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct Data {
Shinya Kitaoka 120a6e
  VectorChangeThicknessTool &m_tool;
Shinya Kitaoka 120a6e
  TVectorImage &m_vi;
Shinya Kitaoka 120a6e
  double m_newThickness;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorChangeThicknessTool::changeImageThickness(
Shinya Kitaoka 120a6e
    TVectorImage &vi, double newThickness) {
Shinya Kitaoka 120a6e
  struct locals {
Shinya Kitaoka 120a6e
    static void changeThickness(const ChangeImageThickness::Data &data, int s) {
Shinya Kitaoka 120a6e
      TStroke &stroke = *data.m_vi.getStroke(s);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      for (int cp = 0; cp < (int)stroke.getControlPointCount(); ++cp) {
Shinya Kitaoka 120a6e
        double thickness =
Shinya Kitaoka 120a6e
            tcrop(data.m_tool.m_strokesThickness[s][cp] + data.m_newThickness,
Shinya Kitaoka 120a6e
                  0.0, 255.0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        TThickPoint point(TPointD(stroke.getControlPoint(cp)), thickness);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        stroke.setControlPoint(cp, point);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  };  // locals
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ChangeImageThickness::Data data = {*this, vi, newThickness};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  VectorSelectionTool *vsTool = static_cast<vectorselectiontool *="">(getTool());</vectorselectiontool>
Shinya Kitaoka 120a6e
  const LevelSelection &levelSelection = vsTool->levelSelection();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (levelSelection.isEmpty()) {
Shinya Kitaoka 120a6e
    StrokeSelection *strokeSelection =
Shinya Kitaoka 120a6e
        static_cast<strokeselection *="">(m_tool->getSelection());</strokeselection>
Shinya Kitaoka 120a6e
    const std::set<int> &selectedStrokeIdxs = strokeSelection->getSelection();</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    std::for_each(selectedStrokeIdxs.begin(), selectedStrokeIdxs.end(),
Shinya Kitaoka 120a6e
                  boost::bind(locals::changeThickness, boost::ref(data), _1));
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    std::vector<int> strokeIdxs = getSelectedStrokes(vi, levelSelection);</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    std::for_each(strokeIdxs.begin(), strokeIdxs.end(),
Shinya Kitaoka 120a6e
                  boost::bind(locals::changeThickness, boost::ref(data), _1));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorChangeThicknessTool::addUndo() {
Shinya Kitaoka 120a6e
  TVectorImageP curVi = getTool()->getImage(true);
Shinya Kitaoka 120a6e
  if (!curVi) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_undo->registerStrokes();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SelectionTool *tool = getTool();
Shinya Kitaoka 120a6e
  if (tool->isLevelType() || tool->isSelectedFramesType()) {
Shinya Kitaoka 120a6e
    VectorSelectionTool *vtool = dynamic_cast<vectorselectiontool *="">(tool);</vectorselectiontool>
Shinya Kitaoka 120a6e
    assert(vtool && !vtool->levelSelection().isEmpty());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TXshSimpleLevel *level =
Shinya Kitaoka 120a6e
        TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Retrieve frames available in the level
Shinya Kitaoka 120a6e
    std::vector<tframeid> fids;</tframeid>
Shinya Kitaoka 120a6e
    level->getFids(fids);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Remove unwanted frames
Shinya Kitaoka 120a6e
    fids.erase(std::remove_if(fids.begin(), fids.end(),
Shinya Kitaoka 120a6e
                              boost::bind(::currentOrNotSelected,
Shinya Kitaoka 120a6e
                                          boost::cref(*vtool), _1)),
Shinya Kitaoka 120a6e
               fids.end());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TUndoManager::manager()->beginBlock();
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      // Current frame added separately
Shinya Kitaoka 120a6e
      TUndoManager::manager()->add(m_undo.release());  // Inside an undo block
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      // Iterate remaining ones
Shinya Kitaoka 120a6e
      int f, fCount = int(fids.size());
Shinya Kitaoka 120a6e
      for (f = 0; f != fCount; ++f) {
Shinya Kitaoka 120a6e
        const TFrameId &fid = fids[f];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        TVectorImageP vi = level->getFrame(fid, true);
Shinya Kitaoka 120a6e
        if (!vi) {
Shinya Kitaoka 120a6e
          assert(vi);
Shinya Kitaoka 120a6e
          continue;
Shinya Kitaoka 120a6e
        }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        // Transform fid's selection
otakuto e28b5e
        std::unique_ptr<undochangestrokes> undo(</undochangestrokes>
Shinya Kitaoka 120a6e
            new UndoChangeStrokes(level, fid, vtool, vtool->levelSelection()));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        setStrokesThickness(*vi);
Shinya Kitaoka 120a6e
        changeImageThickness(*vi, m_thicknessChange);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        m_strokesThickness.clear();
Shinya Kitaoka 120a6e
        undo->registerStrokes();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        TUndoManager::manager()->add(undo.release());
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    TUndoManager::manager()->endBlock();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Finally, notify changed frames
Shinya Kitaoka 120a6e
    std::for_each(fids.begin(), fids.end(),
Shinya Kitaoka 120a6e
                  boost::bind(  // NOTE: current frame is not here - it was
Shinya Kitaoka 120a6e
                      &TTool::notifyImageChanged, m_tool,
Shinya Kitaoka 120a6e
                      _1));  //       aldready notified
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    TUndoManager::manager()->add(m_undo.release());  // Outside any undo block
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorChangeThicknessTool::leftButtonDown(
Shinya Kitaoka 120a6e
    const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_curPos   = pos;
Shinya Kitaoka 120a6e
  m_firstPos = pos;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorChangeThicknessTool::leftButtonDrag(
Shinya Kitaoka 120a6e
    const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  TAffine aff;
Shinya Kitaoka 120a6e
  TPointD delta    = pos - m_curPos;
Shinya Kitaoka 120a6e
  TVectorImageP vi = getTool()->getImage(true);
Shinya Kitaoka 120a6e
  if (!vi) return;
Shinya Kitaoka 120a6e
  m_thicknessChange = (pos.y - m_firstPos.y) * 0.2;
Shinya Kitaoka 120a6e
  changeImageThickness(*vi, m_thicknessChange);
Shinya Kitaoka 120a6e
  getTool()->m_deformValues.m_maxSelectionThickness = m_thicknessChange;
Shinya Kitaoka 120a6e
  getTool()->computeBBox();
Shinya Kitaoka 120a6e
  getTool()->invalidate();
Shinya Kitaoka 120a6e
  m_curPos = pos;
Shinya Kitaoka 120a6e
  getTool()->notifyImageChanged();
Shinya Kitaoka 120a6e
  TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DragSelectionTool::VectorChangeThicknessTool::leftButtonUp(
Shinya Kitaoka 120a6e
    const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  TVectorImageP curVi = getTool()->getImage(true);
Shinya Kitaoka 120a6e
  if (!curVi) return;
Shinya Kitaoka 120a6e
  addUndo();
Shinya Kitaoka 120a6e
  m_strokesThickness.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool getGroupBBox(const TVectorImage &vi, int strokeIndex, TRectD &gBox) {
Shinya Kitaoka 120a6e
  if (!vi.isStrokeGrouped(strokeIndex)) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  gBox = vi.getStroke(strokeIndex)->getBBox();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int s, sCount = int(vi.getStrokeCount());
Shinya Kitaoka 120a6e
  for (s = 0; s != sCount; ++s) {
Shinya Kitaoka 120a6e
    if (vi.sameGroup(s, strokeIndex)) gBox += vi.getStroke(s)->getBBox();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// UndoEnterGroup
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class UndoEnterGroup final : public TUndo {
Shinya Kitaoka 120a6e
  int m_strokeIndex;
Shinya Kitaoka 120a6e
  TVectorImageP m_vi;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  UndoEnterGroup(TVectorImageP vi, int strokeIndex)
Shinya Kitaoka 120a6e
      : m_vi(vi), m_strokeIndex(strokeIndex) {}
Shinya Kitaoka 473e70
  void undo() const override {
Shinya Kitaoka 120a6e
    m_vi->exitGroup();
Shinya Kitaoka 120a6e
    TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 473e70
  void redo() const override {
Shinya Kitaoka 120a6e
    m_vi->enterGroup(m_strokeIndex);
Shinya Kitaoka 120a6e
    TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 473e70
  int getSize() const override { return sizeof(*this); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// UndoExitGroup
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class UndoExitGroup final : public TUndo {
Shinya Kitaoka 120a6e
  int m_strokeIndex;
Shinya Kitaoka 120a6e
  TVectorImageP m_vi;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  UndoExitGroup(TVectorImageP vi, int strokeIndex)
Shinya Kitaoka 120a6e
      : m_vi(vi), m_strokeIndex(strokeIndex) {}
Shinya Kitaoka 473e70
  void undo() const override {
Shinya Kitaoka 120a6e
    m_vi->enterGroup(m_strokeIndex);
Shinya Kitaoka 120a6e
    TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 473e70
  void redo() const override {
Shinya Kitaoka 120a6e
    m_vi->exitGroup();
Shinya Kitaoka 120a6e
    TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  int getSize() const override { return sizeof(*this); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// VectorSelectionTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
VectorSelectionTool::VectorSelectionTool(int targetType)
Shinya Kitaoka 120a6e
    : SelectionTool(targetType)
Shinya Kitaoka 120a6e
    , m_selectionTarget("Mode:")
Shinya Kitaoka 120a6e
    , m_constantThickness("Preserve Thickness", false)
Shinya Kitaoka 120a6e
    , m_levelSelection(m_strokeSelection)
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_selectionCount(0)
Shinya Kitaoka 120a6e
    , m_canEnterGroup(true) {
shun-iwasawa df7bb0
  assert(targetType == TTool::Vectors);
shun-iwasawa df7bb0
  m_prop.bind(m_selectionTarget);
shun-iwasawa df7bb0
  m_prop.bind(m_constantThickness);
shun-iwasawa df7bb0
shun-iwasawa df7bb0
  m_selectionTarget.addValue(NORMAL_TYPE);
shun-iwasawa df7bb0
  m_selectionTarget.addValue(SELECTED_FRAMES_TYPE);
shun-iwasawa df7bb0
  m_selectionTarget.addValue(ALL_LEVEL_TYPE);
shun-iwasawa df7bb0
  m_selectionTarget.addValue(SAME_STYLE_TYPE);
shun-iwasawa df7bb0
  m_selectionTarget.addValue(STYLE_SELECTED_FRAMES_TYPE);
shun-iwasawa df7bb0
  m_selectionTarget.addValue(STYLE_LEVEL_TYPE);
shun-iwasawa df7bb0
  m_selectionTarget.addValue(BOUNDARY_TYPE);
shun-iwasawa df7bb0
  m_selectionTarget.addValue(BOUNDARY_SELECTED_FRAMES_TYPE);
shun-iwasawa df7bb0
  m_selectionTarget.addValue(BOUNDARY_LEVEL_TYPE);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_strokeSelection.setView(this);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_constantThickness.setId("PreserveThickness");
Shinya Kitaoka 120a6e
  m_selectionTarget.setId("SelectionMode");
Shinya Kitaoka 120a6e
shun-iwasawa df7bb0
  m_capStyle.addValue(BUTT_WSTR, QString::fromStdWString(BUTT_WSTR));
shun-iwasawa df7bb0
  m_capStyle.addValue(ROUNDC_WSTR, QString::fromStdWString(ROUNDC_WSTR));
shun-iwasawa df7bb0
  m_capStyle.addValue(PROJECTING_WSTR,
shun-iwasawa df7bb0
                      QString::fromStdWString(PROJECTING_WSTR));
Shinya Kitaoka 120a6e
  m_capStyle.setId("Cap");
Shinya Kitaoka 120a6e
shun-iwasawa df7bb0
  m_joinStyle.addValue(MITER_WSTR, QString::fromStdWString(MITER_WSTR));
shun-iwasawa df7bb0
  m_joinStyle.addValue(ROUNDJ_WSTR, QString::fromStdWString(ROUNDJ_WSTR));
shun-iwasawa df7bb0
  m_joinStyle.addValue(BEVEL_WSTR, QString::fromStdWString(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_outlineProps.bind(m_capStyle);
Shinya Kitaoka 120a6e
  m_outlineProps.bind(m_joinStyle);
Shinya Kitaoka 120a6e
  m_outlineProps.bind(m_miterJoinLimit);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::setNewFreeDeformer() {
Shinya Kitaoka 120a6e
  clearDeformers();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TVectorImageP vi =
Shinya Kitaoka 120a6e
      getImage(true);  // BAD: Should not be done at tool creation...
Shinya Kitaoka 120a6e
  if (!vi) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Current freeDeformer always at index 0
Shinya Kitaoka 120a6e
  m_freeDeformers.push_back(
Shinya Kitaoka 120a6e
      new VectorFreeDeformer(vi, m_strokeSelection.getSelection()));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (isLevelType() || isSelectedFramesType()) {
Shinya Kitaoka 120a6e
    TXshSimpleLevel *level =
Shinya Kitaoka 120a6e
        TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // All SELECTED frames' subsequent freeDeformers are stored sequentially
Shinya Kitaoka 120a6e
    // after that
Shinya Kitaoka 120a6e
    std::vector<tframeid> fids;</tframeid>
Shinya Kitaoka 120a6e
    level->getFids(fids);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    fids.erase(std::remove_if(
Shinya Kitaoka 120a6e
                   fids.begin(), fids.end(),
Shinya Kitaoka 120a6e
                   boost::bind(::currentOrNotSelected, boost::cref(*this), _1)),
Shinya Kitaoka 120a6e
               fids.end());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    std::vector<tframeid>::iterator ft, fEnd = fids.end();</tframeid>
Shinya Kitaoka 120a6e
    for (ft = fids.begin(); ft != fEnd; ++ft) {
Shinya Kitaoka 120a6e
      if (TVectorImageP levelVi = level->getFrame(*ft, false)) {
Shinya Kitaoka 120a6e
        const std::vector<int> &selectedStrokeIdxs =</int>
Shinya Kitaoka 120a6e
            ::getSelectedStrokes(*levelVi, m_levelSelection);
Shinya Kitaoka 120a6e
        std::set<int> strokesIndices(selectedStrokeIdxs.begin(),</int>
Shinya Kitaoka 120a6e
                                     selectedStrokeIdxs.end());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        m_freeDeformers.push_back(
Shinya Kitaoka 120a6e
            new VectorFreeDeformer(levelVi, strokesIndices));
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool VectorSelectionTool::isLevelType() const {
Shinya Kitaoka 120a6e
  return m_levelSelection.framesMode() == LevelSelection::FRAMES_ALL;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool VectorSelectionTool::isSelectedFramesType() const {
Shinya Kitaoka 120a6e
  return m_levelSelection.framesMode() == LevelSelection::FRAMES_SELECTED;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool VectorSelectionTool::isSameStyleType() const {
Shinya Kitaoka 120a6e
  return m_levelSelection.filter() == LevelSelection::SELECTED_STYLES;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool VectorSelectionTool::isModifiableSelectionType() const {
Shinya Kitaoka 120a6e
  return (m_levelSelection.isEmpty() ||
Shinya Kitaoka 120a6e
          m_levelSelection.filter() == LevelSelection::SELECTED_STYLES);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::updateTranslation() {
Shinya Kitaoka 120a6e
  m_selectionTarget.setQStringName(tr("Mode:"));
shun-iwasawa df7bb0
  m_selectionTarget.setItemUIName(NORMAL_TYPE, tr("Standard"));
shun-iwasawa df7bb0
  m_selectionTarget.setItemUIName(SELECTED_FRAMES_TYPE, tr("Selected Frames"));
shun-iwasawa df7bb0
  m_selectionTarget.setItemUIName(ALL_LEVEL_TYPE, tr("Whole Level"));
shun-iwasawa df7bb0
  m_selectionTarget.setItemUIName(SAME_STYLE_TYPE, tr("Same Style"));
shun-iwasawa df7bb0
  m_selectionTarget.setItemUIName(STYLE_SELECTED_FRAMES_TYPE,
shun-iwasawa df7bb0
                                  tr("Same Style on Selected Frames"));
shun-iwasawa df7bb0
  m_selectionTarget.setItemUIName(STYLE_LEVEL_TYPE,
shun-iwasawa df7bb0
                                  tr("Same Style on Whole Level"));
shun-iwasawa df7bb0
  m_selectionTarget.setItemUIName(BOUNDARY_TYPE, tr("Boundary Strokes"));
shun-iwasawa df7bb0
  m_selectionTarget.setItemUIName(BOUNDARY_SELECTED_FRAMES_TYPE,
shun-iwasawa df7bb0
                                  tr("Boundaries on Selected Frames"));
shun-iwasawa df7bb0
  m_selectionTarget.setItemUIName(BOUNDARY_LEVEL_TYPE,
shun-iwasawa df7bb0
                                  tr("Boundaries on Whole Level"));
shun-iwasawa df7bb0
Shinya Kitaoka 120a6e
  m_constantThickness.setQStringName(tr("Preserve Thickness"));
shun-iwasawa df7bb0
Shinya Kitaoka 120a6e
  m_capStyle.setQStringName(tr("Cap"));
shun-iwasawa df7bb0
  m_capStyle.setItemUIName(BUTT_WSTR, tr("Butt cap"));
shun-iwasawa df7bb0
  m_capStyle.setItemUIName(ROUNDC_WSTR, tr("Round cap"));
shun-iwasawa df7bb0
  m_capStyle.setItemUIName(PROJECTING_WSTR, tr("Projecting cap"));
shun-iwasawa df7bb0
Shinya Kitaoka 120a6e
  m_joinStyle.setQStringName(tr("Join"));
shun-iwasawa df7bb0
  m_joinStyle.setItemUIName(MITER_WSTR, tr("Miter join"));
shun-iwasawa df7bb0
  m_joinStyle.setItemUIName(ROUNDJ_WSTR, tr("Round join"));
shun-iwasawa df7bb0
  m_joinStyle.setItemUIName(BEVEL_WSTR, tr("Bevel join"));
shun-iwasawa df7bb0
Shinya Kitaoka 120a6e
  m_miterJoinLimit.setQStringName(tr("Miter:"));
Shinya Kitaoka 120a6e
  SelectionTool::updateTranslation();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::updateSelectionTarget() {
Shinya Kitaoka 120a6e
  // Make the correct selection current
Shinya Kitaoka 120a6e
  if (m_selectionTarget.getIndex() == NORMAL_TYPE_IDX) {
Shinya Kitaoka 120a6e
    std::set<int> selectedStrokes;  // Retain previously selected strokes across</int>
Shinya Kitaoka 120a6e
    selectedStrokes.swap(
Shinya Kitaoka 120a6e
        m_strokeSelection.getSelection());  // current selection change
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_strokeSelection
Shinya Kitaoka 120a6e
        .makeCurrent();  // Empties any (different) previously current
Shinya Kitaoka 120a6e
                         // selection on its own
Shinya Kitaoka 120a6e
    selectedStrokes.swap(m_strokeSelection.getSelection());
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_levelSelection.makeCurrent();  // Same here
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Choose frames mode
Shinya Kitaoka 120a6e
  LevelSelection::FramesMode framesMode;
Shinya Kitaoka 120a6e
  switch (m_selectionTarget.getIndex()) {
Shinya Kitaoka 120a6e
  case SAME_STYLE_TYPE_IDX:
Shinya Kitaoka 120a6e
  case BOUNDARY_TYPE_IDX:
Shinya Kitaoka 120a6e
    framesMode = LevelSelection::FRAMES_CURRENT;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  case ALL_LEVEL_TYPE_IDX:
Shinya Kitaoka 120a6e
  case STYLE_LEVEL_TYPE_IDX:
Shinya Kitaoka 120a6e
  case BOUNDARY_LEVEL_TYPE_IDX:
Shinya Kitaoka 120a6e
    framesMode = LevelSelection::FRAMES_ALL;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  case SELECTED_FRAMES_TYPE_IDX:
Shinya Kitaoka 120a6e
  case STYLE_SELECTED_FRAMES_TYPE_IDX:
Shinya Kitaoka 120a6e
  case BOUNDARY_SELECTED_FRAMES_TYPE_IDX:
Shinya Kitaoka 120a6e
    framesMode = LevelSelection::FRAMES_SELECTED;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (framesMode != m_levelSelection.framesMode()) clearSelectedStrokes();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_levelSelection.framesMode() = framesMode;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Choose filter
Shinya Kitaoka 120a6e
  LevelSelection::Filter filter;
Shinya Kitaoka 120a6e
  switch (m_selectionTarget.getIndex()) {
Shinya Kitaoka 120a6e
  case SELECTED_FRAMES_TYPE_IDX:
Shinya Kitaoka 120a6e
  case ALL_LEVEL_TYPE_IDX:
Shinya Kitaoka 120a6e
    filter = LevelSelection::WHOLE;
Shinya Kitaoka 120a6e
    selectedStyles().clear();
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  case SAME_STYLE_TYPE_IDX:
Shinya Kitaoka 120a6e
  case STYLE_SELECTED_FRAMES_TYPE_IDX:
Shinya Kitaoka 120a6e
  case STYLE_LEVEL_TYPE_IDX:
Shinya Kitaoka 120a6e
    filter = LevelSelection::SELECTED_STYLES;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  case BOUNDARY_TYPE_IDX:
Shinya Kitaoka 120a6e
  case BOUNDARY_SELECTED_FRAMES_TYPE_IDX:
Shinya Kitaoka 120a6e
  case BOUNDARY_LEVEL_TYPE_IDX:
Shinya Kitaoka 120a6e
    filter = LevelSelection::BOUNDARY_STROKES;
Shinya Kitaoka 120a6e
    selectedStyles().clear();
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (filter != m_levelSelection.filter()) clearSelectedStrokes();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_levelSelection.filter() = filter;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::finalizeSelection() {
Shinya Kitaoka 120a6e
  TVectorImageP vi = getImage(false);
Shinya Kitaoka 120a6e
  if (vi && !m_levelSelection.isEmpty()) {
Shinya Kitaoka 120a6e
    std::set<int> &selection = m_strokeSelection.getSelection();</int>
Shinya Kitaoka 120a6e
    selection.clear();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Apply base additive selection
Shinya Kitaoka 120a6e
    if (!isSelectedFramesType() || m_selectedFrames.count(getCurrentFid())) {
Shinya Kitaoka 120a6e
      // Apply filters
Shinya Kitaoka 120a6e
      std::vector<int> selectedStrokes =</int>
Shinya Kitaoka 120a6e
          getSelectedStrokes(*vi, m_levelSelection);
Shinya Kitaoka 120a6e
      std::set<int>(selectedStrokes.begin(), selectedStrokes.end())</int>
Shinya Kitaoka 120a6e
          .swap(selection);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  computeBBox();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TTool::getApplication()
Shinya Kitaoka 120a6e
      ->getCurrentTool()
Shinya Kitaoka 120a6e
      ->notifyToolChanged();  // Refreshes toolbar values
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::clearSelectedStrokes() {
Shinya Kitaoka 120a6e
  m_strokeSelection.selectNone();
Shinya Kitaoka 120a6e
  m_levelSelection.styles().clear();
Shinya Kitaoka 120a6e
  m_deformValues.reset();
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::modifySelectionOnClick(TImageP image,
Shinya Kitaoka 120a6e
                                                 const TPointD &pos,
Shinya Kitaoka 120a6e
                                                 const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  TVectorImageP vi = TVectorImageP(image);
Shinya Kitaoka 120a6e
  assert(m_strokeSelection.getImage() == vi);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!vi) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  updateSelectionTarget();  // Make selection current. This is necessary in case
Shinya Kitaoka 120a6e
  // some other selection context made another selection current.
Shinya Kitaoka 120a6e
  m_firstPos = m_curPos = pos;
Shinya Kitaoka 120a6e
  m_selectingRect       = FourPoints();
Shinya Kitaoka 120a6e
  m_selecting           = false;
Shinya Kitaoka 120a6e
  m_justSelected        = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  updateAction(pos, e);
Shinya Kitaoka 120a6e
  if (m_what != Inside && m_what != Outside && m_what != ADD_SELECTION) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  UINT index         = 0;
Shinya Kitaoka 120a6e
  bool modifiableSel = isModifiableSelectionType(),
Shinya Kitaoka 120a6e
       strokeAtPos   = getStrokeIndexFromPos(index, vi, pos, getPixelSize()),
Shinya Kitaoka 120a6e
       addStroke     = strokeAtPos && !m_strokeSelection.isSelected(index),
Shinya Kitaoka 120a6e
       toggleStroke  = strokeAtPos && e.isShiftPressed();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_selecting =
Shinya Kitaoka 120a6e
      (modifiableSel && !strokeAtPos  // There must be no stroke under cursor
Shinya Kitaoka 120a6e
       && (e.isShiftPressed()  // and either the user is explicitly performing
Shinya Kitaoka 120a6e
                               // additional selection
Shinya Kitaoka 120a6e
           || (m_strokeSelectionType.getIndex() !=
Shinya Kitaoka 120a6e
               POLYLINE_SELECTION_IDX)  // or the tool support immediate
Shinya Kitaoka 120a6e
                                        // selection on clear
Shinya Kitaoka 120a6e
           ||
Shinya Kitaoka 120a6e
           m_strokeSelection
Shinya Kitaoka 120a6e
               .isEmpty()));  // or the strokes list was already cleared
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool clearTargets     = !(strokeAtPos || e.isShiftPressed() || m_selecting),
Shinya Kitaoka 120a6e
       clearSelection   = (addStroke || !strokeAtPos) && !e.isShiftPressed(),
Shinya Kitaoka 120a6e
       selectionChanged = clearSelection;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(clearTargets ? clearSelection : true);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (clearTargets) m_levelSelection.selectNone();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (clearSelection) {
Shinya Kitaoka 120a6e
    m_strokeSelection.selectNone();
Shinya Kitaoka 120a6e
    selectedStyles().clear();  // Targets are preserved here
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (strokeAtPos)
Shinya Kitaoka 120a6e
    selectionChanged = m_justSelected = selectStroke(index, toggleStroke);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (selectionChanged) {
Shinya Kitaoka 120a6e
    m_deformValues.reset();  // Resets selection values shown in the toolbar
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    finalizeSelection();
Shinya Kitaoka 120a6e
    notifySelectionChanged();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::leftButtonDoubleClick(const TPointD &pos,
Shinya Kitaoka 120a6e
                                                const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  TVectorImageP vi = getImage(false);
Shinya Kitaoka 120a6e
  if (!vi) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_strokeSelectionType.getIndex() == POLYLINE_SELECTION_IDX &&
Shinya Kitaoka 120a6e
      !m_polyline.empty()) {
Shinya Kitaoka 120a6e
    closePolyline(pos);
Shinya Kitaoka 120a6e
    selectRegionVectorImage();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_selecting = false;
Shinya Kitaoka 120a6e
    invalidate();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int strokeIndex;
Shinya Kitaoka 120a6e
  if ((strokeIndex = vi->pickGroup(pos)) >= 0) {
Shinya Kitaoka 120a6e
    if (vi->canEnterGroup(strokeIndex) && m_canEnterGroup) {
Shinya Kitaoka 120a6e
      if (vi->enterGroup(strokeIndex)) {
Shinya Kitaoka 120a6e
        clearSelectedStrokes();
Shinya Kitaoka 120a6e
        TUndoManager::manager()->add(new UndoEnterGroup(vi, strokeIndex));
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else if ((strokeIndex = vi->exitGroup()) >= 0)
Shinya Kitaoka 120a6e
    TUndoManager::manager()->add(new UndoExitGroup(vi, strokeIndex));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  finalizeSelection();
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::leftButtonDrag(const TPointD &pos,
Shinya Kitaoka 120a6e
                                         const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  if (m_dragTool) {
Shinya Kitaoka 120a6e
    m_dragTool->leftButtonDrag(pos, e);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TVectorImageP vi = getImage(false);
Shinya Kitaoka 120a6e
  if (!vi) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double pixelSize        = getPixelSize();
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!app || m_justSelected || !m_selecting ||
Shinya Kitaoka 120a6e
      tdistance2(pos, m_curPos) < 9.0 * pixelSize * pixelSize)
Shinya Kitaoka 120a6e
    return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_curPos = pos;
Toshihiro Shimizu 890ddd
shun-iwasawa c189d1
  if (m_strokeSelectionType.getIndex() == FREEHAND_SELECTION_IDX) {
Shinya Kitaoka 120a6e
    freehandDrag(pos);
shun-iwasawa c189d1
    invalidate();
shun-iwasawa c189d1
  } else if (m_strokeSelectionType.getIndex() == RECT_SELECTION_IDX) {
Shinya Kitaoka 120a6e
    bool selectOverlappingStroke = (m_firstPos.x > pos.x);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TRectD rect(m_firstPos, pos);
Shinya Kitaoka 120a6e
    m_selectingRect = rect;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    std::set<int> oldSelection;</int>
Shinya Kitaoka 120a6e
    if (m_shiftPressed) oldSelection = m_strokeSelection.getSelection();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    clearSelectedStrokes();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    QMutexLocker lock(vi->getMutex());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_strokeSelection.setImage(vi);  // >_<  Shouldn't be done here...?
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    bool selectionChanged = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    int s, sCount = vi->getStrokeCount();
Shinya Kitaoka 120a6e
    for (s = 0; s != sCount; ++s) {
Shinya Kitaoka 120a6e
      if (!vi->isEnteredGroupStroke(s)) continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      TStroke *stroke = vi->getStroke(s);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      if (m_strokeSelection.isSelected(s)) continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      bool inSelection = selectOverlappingStroke
Shinya Kitaoka 120a6e
                             ? rect.overlaps(stroke->getBBox())
Shinya Kitaoka 120a6e
                             : rect.contains(stroke->getBBox());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      if (inSelection || (m_shiftPressed && oldSelection.count(s)))
Shinya Kitaoka 120a6e
        selectionChanged = (selectStroke(s, false) || selectionChanged);
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (selectionChanged) finalizeSelection();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::leftButtonUp(const TPointD &pos,
Shinya Kitaoka 120a6e
                                       const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_leftButtonMousePressed = false;
Shinya Kitaoka 120a6e
  m_shiftPressed           = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_dragTool) {
Shinya Kitaoka 120a6e
    m_dragTool->leftButtonUp(pos, e);
Shinya Kitaoka 120a6e
    delete m_dragTool;
Shinya Kitaoka 120a6e
    m_dragTool = 0;
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_selecting) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Complete selection
Shinya Kitaoka 120a6e
  TVectorImageP vi = getImage(false);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (vi) {
Shinya Kitaoka 120a6e
    if (m_strokeSelectionType.getIndex() == RECT_SELECTION_IDX)
Shinya Kitaoka 120a6e
      notifySelectionChanged();
Shinya Kitaoka 120a6e
    else if (m_strokeSelectionType.getIndex() == FREEHAND_SELECTION_IDX) {
Shinya Kitaoka 120a6e
      QMutexLocker lock(vi->getMutex());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      closeFreehand(pos);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      if (m_stroke->getControlPointCount() > 3) selectRegionVectorImage();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      delete m_stroke;  // >:(
Shinya Kitaoka 120a6e
      m_stroke = 0;
shun-iwasawa c189d1
      m_track.clear();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_selecting    = false;
Shinya Kitaoka 120a6e
  m_justSelected = false;
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::addContextMenuItems(QMenu *menu) {
Shinya Kitaoka 120a6e
  menu->addAction(CommandManager::instance()->getAction(MI_RemoveEndpoints));
Shinya Kitaoka 120a6e
  menu->addSeparator();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_strokeSelection.getGroupCommand()->addMenuItems(menu);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::drawInLevelType(const TVectorImage &vi) {
Shinya Kitaoka 120a6e
  glPushMatrix();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  FourPoints bbox = getBBox();
Shinya Kitaoka 120a6e
  if (!bbox.isEmpty()) {
Shinya Kitaoka 120a6e
    TPixel32 frameColor(127, 127, 127);
Shinya Kitaoka 120a6e
    double pixelSize = getPixelSize();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    drawFourPoints(bbox, TPixel32::Black, 0x5555, true);
Shinya Kitaoka 120a6e
    drawFourPoints(bbox.enlarge(pixelSize * (-4)), frameColor, 0xffff, true);
Shinya Kitaoka 120a6e
    drawFourPoints(bbox.enlarge(pixelSize * (-2)), frameColor, 0x8888, true);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    drawCommandHandle(&vi);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  drawSelectedStrokes(vi);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_selecting && !m_selectingRect.isEmpty()) drawRectSelection(&vi);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_strokeSelectionType.getIndex() == POLYLINE_SELECTION_IDX)
Shinya Kitaoka 120a6e
    drawPolylineSelection();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glPopMatrix();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::drawSelectedStrokes(const TVectorImage &vi) {
Shinya Kitaoka 120a6e
  glEnable(GL_LINE_STIPPLE);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double pixelSize = getPixelSize();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int s, sCount = vi.getStrokeCount();
Shinya Kitaoka 120a6e
  for (s = 0; s != sCount; ++s) {
Shinya Kitaoka 120a6e
    if (m_strokeSelection.isSelected(s)) {
Shinya Kitaoka 120a6e
      TStroke *stroke = vi.getStroke(s);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      glLineStipple(1, 0xF0F0);
Shinya Kitaoka 120a6e
      tglColor(TPixel32::Black);
Shinya Kitaoka 120a6e
      drawStrokeCenterline(*stroke, pixelSize);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      glLineStipple(1, 0x0F0F);
Shinya Kitaoka 120a6e
      tglColor(TPixel32::White);
Shinya Kitaoka 120a6e
      drawStrokeCenterline(*stroke, pixelSize);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glDisable(GL_LINE_STIPPLE);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::drawGroup(const TVectorImage &vi) {
Shinya Kitaoka 120a6e
  int s, sCount = vi.getStrokeCount();
Shinya Kitaoka 120a6e
  for (s = 0; s != sCount; ++s) {
Shinya Kitaoka 120a6e
    if (m_strokeSelection.isSelected(s)) {
Shinya Kitaoka 120a6e
      TRectD gBox;
Shinya Kitaoka 120a6e
      if (getGroupBBox(vi, s, gBox)) drawRect(gBox, TPixel::Blue, 0xffff);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::draw() {
Shinya Kitaoka 120a6e
  TVectorImageP vi = getImage(false);
Shinya Kitaoka 120a6e
  if (!vi) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (isLevelType() || isSelectedFramesType()) {
Shinya Kitaoka 120a6e
    drawInLevelType(*vi);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glPushMatrix();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_strokeSelection.isEmpty())       // o_o  WTF!?
Shinya Kitaoka 120a6e
    m_bboxs.clear(), m_centers.clear();  //
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // common draw
Shinya Kitaoka 120a6e
  if (getBBoxsCount() > 0) drawCommandHandle(vi.getPointer());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_selecting && !m_selectingRect.isEmpty())
Shinya Kitaoka 120a6e
    drawRectSelection(vi.getPointer());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRectD bbox = vi->getBBox();
Shinya Kitaoka 120a6e
  TPixel32 frameColor(140, 140, 140);
Shinya Kitaoka 120a6e
  tglColor(frameColor);
Shinya Kitaoka 120a6e
  drawRect(bbox, frameColor, 0x5555, true);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  drawSelectedStrokes(*vi);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_strokeSelectionType.getIndex() == POLYLINE_SELECTION_IDX)
Shinya Kitaoka 120a6e
    drawPolylineSelection();
shun-iwasawa c189d1
  else if (m_strokeSelectionType.getIndex() == FREEHAND_SELECTION_IDX)
shun-iwasawa c189d1
    drawFreehandSelection();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_levelSelection.isEmpty()) drawGroup(*vi);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glPopMatrix();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TSelection *VectorSelectionTool::getSelection() {
Shinya Kitaoka 120a6e
  TImage *image    = getImage(false);
Shinya Kitaoka 120a6e
  TVectorImageP vi = image;
Shinya Kitaoka 120a6e
  if (!vi) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return &m_strokeSelection;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool VectorSelectionTool::isSelectionEmpty() {
Shinya Kitaoka 120a6e
  TVectorImageP vi =
Shinya Kitaoka 120a6e
      getImage(false);  // We want at least current image to be visible.
Shinya Kitaoka 120a6e
  if (!vi)              // This is somewhat in line to preventing tool actions
Shinya Kitaoka 120a6e
    return true;        // on non-visible levels.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return m_strokeSelection
Shinya Kitaoka 120a6e
      .isEmpty();  // Same here, something should be visibly selected.
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::computeBBox() {
Shinya Kitaoka 120a6e
  m_bboxs.clear();
Shinya Kitaoka 120a6e
  m_centers.clear();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TVectorImageP vi = getImage(false);
Shinya Kitaoka 120a6e
  if (!vi) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (isLevelType() || isSelectedFramesType()) {
Shinya Kitaoka 120a6e
    double maxThickness = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Calculate current image's bbox - it is always the first one (index 0)
Shinya Kitaoka 120a6e
    if (vi && (isLevelType() || m_selectedFrames.count(getCurrentFid()) > 0)) {
Shinya Kitaoka 120a6e
      FourPoints bbox =
Shinya Kitaoka 120a6e
          getFourPointsFromVectorImage(vi, selectedStyles(), maxThickness);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_bboxs.push_back(bbox);
Shinya Kitaoka 120a6e
      m_centers.push_back((bbox.getP00() + bbox.getP11()) * 0.5);
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // All subsequent SELECTED frames' bboxes come sequentially starting from 1
Shinya Kitaoka 120a6e
    if (TXshSimpleLevel *level =
Shinya Kitaoka 120a6e
            TTool::getApplication()->getCurrentLevel()->getSimpleLevel()) {
Shinya Kitaoka 120a6e
      std::vector<tframeid> fids;</tframeid>
Shinya Kitaoka 120a6e
      level->getFids(fids);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      for (int i = 0; i < (int)fids.size(); ++i) {
Shinya Kitaoka 120a6e
        if (getCurrentFid() == fids[i] ||
Shinya Kitaoka 120a6e
            (isSelectedFramesType() && m_selectedFrames.count(fids[i]) == 0))
Shinya Kitaoka 120a6e
          continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        TVectorImageP vi = level->getFrame(fids[i], false);
Shinya Kitaoka 120a6e
        if (!vi) continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        FourPoints p =
Shinya Kitaoka 120a6e
            getFourPointsFromVectorImage(vi, selectedStyles(), maxThickness);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        m_bboxs.push_back(p);
Shinya Kitaoka 120a6e
        m_centers.push_back(0.5 * (p.getP00() + p.getP11()));
Shinya Kitaoka 120a6e
        m_deformValues.m_maxSelectionThickness = maxThickness;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else if (vi) {
Shinya Kitaoka 120a6e
    TRectD newBbox;
Shinya Kitaoka 120a6e
    double maxThickness = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    for (int i = 0; i < (int)vi->getStrokeCount(); i++) {
Shinya Kitaoka 120a6e
      TStroke *stroke = vi->getStroke(i);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      if (m_strokeSelection.isSelected(i)) {
Shinya Kitaoka 120a6e
        newBbox += stroke->getBBox();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        for (int j = 0; j < stroke->getControlPointCount(); j++) {
Shinya Kitaoka 120a6e
          double thick = stroke->getControlPoint(j).thick;
Shinya Kitaoka 120a6e
          if (maxThickness < thick) maxThickness = thick;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_deformValues.m_maxSelectionThickness = maxThickness;
Shinya Kitaoka 120a6e
    FourPoints bbox;
Shinya Kitaoka 120a6e
    bbox = newBbox;
Shinya Kitaoka 120a6e
    m_bboxs.push_back(bbox);
Shinya Kitaoka 120a6e
    m_centers.push_back(0.5 * (bbox.getP11() + bbox.getP00()));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ++m_selectionCount;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool VectorSelectionTool::selectStroke(int index, bool toggle) {
Shinya Kitaoka 120a6e
  TVectorImageP vi = getImage(false);
Shinya Kitaoka 120a6e
  assert(vi);
Shinya Kitaoka 120a6e
  assert(m_strokeSelection.getImage() == vi);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!vi->isEnteredGroupStroke(index))  // If index is not in current group
Shinya Kitaoka 120a6e
    return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (index < 0 || index >= int(vi->getStrokeCount()))  // Should be asserted...
Shinya Kitaoka 120a6e
    return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool wasSelected = m_strokeSelection.isSelected(index),
Shinya Kitaoka 120a6e
       selectState = !(wasSelected && toggle);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // (De)Select additional strokes related to ours
Shinya Kitaoka 120a6e
  std::set<int> &selectedStyles = this->selectedStyles();</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (isSameStyleType())  // Color selection
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    TStroke *refStroke = vi->getStroke(index);
Shinya Kitaoka 120a6e
    assert(refStroke);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    int style = refStroke->getStyle();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (selectState)
Shinya Kitaoka 120a6e
      selectedStyles.insert(style);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      selectedStyles.erase(style);
Shinya Kitaoka 120a6e
  } else if (vi->isStrokeGrouped(index) &&
Shinya Kitaoka 120a6e
             vi->selectable(index))  // Group selection
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    int s, sCount = vi->getStrokeCount();
Shinya Kitaoka 120a6e
    for (s = 0; s != sCount; ++s) {
Shinya Kitaoka 120a6e
      if (vi->selectable(s) && vi->sameSubGroup(index, s))
Shinya Kitaoka 120a6e
        m_strokeSelection.select(s, selectState);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  // Single stroke selection
Shinya Kitaoka 120a6e
    m_strokeSelection.select(index, selectState);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return (selectState != wasSelected);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::onActivate() {
Shinya Kitaoka 120a6e
  if (m_firstTime) {
Shinya Kitaoka 120a6e
    m_constantThickness.setValue(l_strokeSelectConstantThickness ? 1 : 0);
Shinya Kitaoka 120a6e
    m_strokeSelection.setSceneHandle(
Shinya Kitaoka 120a6e
        TTool::getApplication()->getCurrentScene());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SelectionTool::onActivate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::onDeactivate() {
Shinya Kitaoka 120a6e
  if (isLevelType()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SelectionTool::onDeactivate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::doOnActivate() {
Shinya Kitaoka 120a6e
  TVectorImageP vi = getImage(false);
Shinya Kitaoka 120a6e
  m_strokeSelection.setImage(vi);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  updateSelectionTarget();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  finalizeSelection();
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::onImageChanged() {
Shinya Kitaoka 120a6e
  TVectorImageP vi          = getImage(false);
Shinya Kitaoka 120a6e
  TVectorImageP selectedImg = m_strokeSelection.getImage();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (vi != selectedImg) {
Shinya Kitaoka 120a6e
    m_strokeSelection.selectNone();
Shinya Kitaoka 120a6e
    m_strokeSelection.setImage(vi);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (!(vi && selectedImg)  // Retain the styles selection ONLY
Shinya Kitaoka 120a6e
        ||
Shinya Kitaoka 120a6e
        vi->getPalette() !=
Shinya Kitaoka 120a6e
            selectedImg->getPalette())  // if palettes still match
Shinya Kitaoka 120a6e
      selectedStyles().clear();
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    // Remove any eventual stroke index outside the valid range
Shinya Kitaoka 120a6e
    if (!m_strokeSelection.isEmpty()) {
Shinya Kitaoka 120a6e
      const std::set<int> &indexes = m_strokeSelection.getSelection();</int>
Shinya Kitaoka 120a6e
      int strokesCount             = selectedImg->getStrokeCount();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      std::set<int>::const_iterator it;</int>
Shinya Kitaoka 120a6e
      for (it = indexes.begin(); it != indexes.end(); ++it) {
Shinya Kitaoka 120a6e
        int index = *it;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        if (index >= strokesCount) m_strokeSelection.select(index, false);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  finalizeSelection();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::doOnDeactivate() {
Shinya Kitaoka 120a6e
  m_strokeSelection.selectNone();
Shinya Kitaoka 120a6e
  m_levelSelection.selectNone();
Shinya Kitaoka 120a6e
  m_deformValues.reset();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_polyline.clear();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TTool::getApplication()->getCurrentSelection()->setSelection(0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPropertyGroup *VectorSelectionTool::getProperties(int idx) {
Shinya Kitaoka 120a6e
  switch (idx) {
Shinya Kitaoka 120a6e
  case 0:
Shinya Kitaoka 120a6e
    return &m_prop;
Shinya Kitaoka 120a6e
  case 1:
Shinya Kitaoka 120a6e
    return &m_outlineProps;
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    return 0;
Shinya Kitaoka 120a6e
  };
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool VectorSelectionTool::onPropertyChanged(std::string propertyName) {
Shinya Kitaoka 120a6e
  if (SelectionTool::onPropertyChanged(propertyName)) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (propertyName == m_constantThickness.getName())
Shinya Kitaoka 120a6e
    l_strokeSelectConstantThickness = (int)(m_constantThickness.getValue());
Shinya Kitaoka 120a6e
  else if (propertyName == m_selectionTarget.getName())
Shinya Kitaoka 120a6e
    doOnActivate();
Shinya Kitaoka 120a6e
  else if (propertyName == m_capStyle.getName()) {
Shinya Kitaoka 120a6e
    if (m_strokeSelection.isEmpty()) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TXshSimpleLevel *level =
Shinya Kitaoka 120a6e
        TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Shinya Kitaoka 120a6e
    UndoChangeOutlineStyle *undo =
Shinya Kitaoka 120a6e
        new UndoChangeOutlineStyle(level, getCurrentFid(), this);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    int newCapStyle = m_capStyle.getIndex();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TVectorImageP vi = m_strokeSelection.getImage();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    const std::set<int> &indices = m_strokeSelection.getSelection();</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    std::set<int>::iterator it;</int>
Shinya Kitaoka 120a6e
    for (it = indices.begin(); it != indices.end(); ++it) {
Shinya Kitaoka 120a6e
      TStroke *stroke = vi->getStroke(*it);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      stroke->outlineOptions().m_capStyle =
Shinya Kitaoka 120a6e
          (TStroke::OutlineOptions::CapStyle)newCapStyle;
Shinya Kitaoka 120a6e
      stroke->invalidate();
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    computeBBox();
Shinya Kitaoka 120a6e
    invalidate();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    level->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    undo->registerStrokes();
Shinya Kitaoka 120a6e
    TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    notifyImageChanged();
Shinya Kitaoka 120a6e
  } else if (propertyName == m_joinStyle.getName()) {
Shinya Kitaoka 120a6e
    if (m_strokeSelection.isEmpty()) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TXshSimpleLevel *level =
Shinya Kitaoka 120a6e
        TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Shinya Kitaoka 120a6e
    UndoChangeOutlineStyle *undo =
Shinya Kitaoka 120a6e
        new UndoChangeOutlineStyle(level, getCurrentFid(), this);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    int newJoinStyle = m_joinStyle.getIndex();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TVectorImageP vi = m_strokeSelection.getImage();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    const std::set<int> &indices = m_strokeSelection.getSelection();</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    std::set<int>::iterator it;</int>
Shinya Kitaoka 120a6e
    for (it = indices.begin(); it != indices.end(); ++it) {
Shinya Kitaoka 120a6e
      TStroke *stroke = vi->getStroke(*it);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      stroke->outlineOptions().m_joinStyle =
Shinya Kitaoka 120a6e
          (TStroke::OutlineOptions::JoinStyle)newJoinStyle;
Shinya Kitaoka 120a6e
      stroke->invalidate();
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    computeBBox();
Shinya Kitaoka 120a6e
    invalidate();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    level->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    undo->registerStrokes();
Shinya Kitaoka 120a6e
    TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    notifyImageChanged();
Shinya Kitaoka 120a6e
  } else if (propertyName == m_miterJoinLimit.getName()) {
Shinya Kitaoka 120a6e
    if (m_strokeSelection.isEmpty()) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TXshSimpleLevel *level =
Shinya Kitaoka 120a6e
        TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Shinya Kitaoka 120a6e
    UndoChangeOutlineStyle *undo =
Shinya Kitaoka 120a6e
        new UndoChangeOutlineStyle(level, getCurrentFid(), this);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    int upper = m_miterJoinLimit.getValue();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TVectorImageP vi = m_strokeSelection.getImage();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    const std::set<int> &indices = m_strokeSelection.getSelection();</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    std::set<int>::iterator it;</int>
Shinya Kitaoka 120a6e
    for (it = indices.begin(); it != indices.end(); ++it) {
Shinya Kitaoka 120a6e
      TStroke *stroke = vi->getStroke(*it);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      stroke->outlineOptions().m_miterUpper = upper;
Shinya Kitaoka 120a6e
      stroke->invalidate();
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    computeBBox();
Shinya Kitaoka 120a6e
    invalidate();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    level->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    undo->registerStrokes();
Shinya Kitaoka 120a6e
    TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    notifyImageChanged();
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::selectionOutlineStyle(int &capStyle, int &joinStyle) {
Shinya Kitaoka 120a6e
  // Check the selection's outline style group validity
Shinya Kitaoka 120a6e
  const std::set<int> &selection = m_strokeSelection.getSelection();</int>
Shinya Kitaoka 120a6e
  if (selection.empty()) {
Shinya Kitaoka 120a6e
    capStyle = joinStyle = -1;
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TVectorImageP vi = m_strokeSelection.getImage();
Shinya Kitaoka 120a6e
  const TStroke::OutlineOptions &beginOptions =
Shinya Kitaoka 120a6e
      vi->getStroke(*selection.begin())->outlineOptions();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  capStyle  = beginOptions.m_capStyle;
Shinya Kitaoka 120a6e
  joinStyle = beginOptions.m_joinStyle;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::set<int>::const_iterator it;</int>
Shinya Kitaoka 120a6e
  for (it = selection.begin(); it != selection.end(); ++it) {
Shinya Kitaoka 120a6e
    const TStroke::OutlineOptions &options =
Shinya Kitaoka 120a6e
        vi->getStroke(*it)->outlineOptions();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (capStyle != options.m_capStyle) capStyle    = -1;
Shinya Kitaoka 120a6e
    if (joinStyle != options.m_joinStyle) joinStyle = -1;
Shinya Kitaoka 120a6e
    if (capStyle < 0 && joinStyle < 0) return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::selectRegionVectorImage() {
Shinya Kitaoka 120a6e
  if (!m_stroke) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TVectorImageP vi(getImage(false));
Shinya Kitaoka 120a6e
  if (!vi) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_strokeSelection.setImage(vi);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TVectorImage selectImg;
Shinya Kitaoka 120a6e
  selectImg.addStroke(new TStroke(*m_stroke));
Shinya Kitaoka 120a6e
  selectImg.findRegions();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int sCount = int(vi->getStrokeCount()),
Shinya Kitaoka 120a6e
      rCount = int(selectImg.getRegionCount());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool selectionChanged = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (int s = 0; s != sCount; ++s) {
Shinya Kitaoka 120a6e
    TStroke *currentStroke = vi->getStroke(s);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    for (int r = 0; r != rCount; ++r) {
Shinya Kitaoka 120a6e
      TRegion *region = selectImg.getRegion(r);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      if (region->contains(*currentStroke, true))
Shinya Kitaoka 120a6e
        selectionChanged = selectStroke(s, false) || selectionChanged;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (selectionChanged) {
Shinya Kitaoka 120a6e
    finalizeSelection();
Shinya Kitaoka 120a6e
    notifySelectionChanged();
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::updateAction(TPointD pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  TImageP image    = getImage(false);
Shinya Kitaoka 120a6e
  TVectorImageP vi = (TVectorImageP)image;
Shinya Kitaoka 120a6e
  if (!vi) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SelectionTool::updateAction(pos, e);
Shinya Kitaoka 120a6e
  if (m_what != Outside || m_cursorId != ToolCursor::StrokeSelectCursor) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  FourPoints bbox = getBBox();
Shinya Kitaoka 120a6e
  UINT index      = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if ((isLevelType() &&
Shinya Kitaoka 120a6e
       bbox.contains(pos))  // What about isSelectedFramesType()??
Shinya Kitaoka 120a6e
      || (getStrokeIndexFromPos(index, vi, pos, getPixelSize()) &&
Shinya Kitaoka 120a6e
          m_strokeSelection.isSelected(index))) {
Shinya Kitaoka 120a6e
    m_what = Inside;
Shinya Kitaoka 120a6e
    m_cursorId =
Shinya Kitaoka 120a6e
        isLevelType() ? ToolCursor::LevelSelectCursor : ToolCursor::MoveCursor;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void VectorSelectionTool::onSelectedFramesChanged() {
Shinya Kitaoka 120a6e
  if (isSelectedFramesType())  // False also in case m_levelSelection is not
Shinya Kitaoka 120a6e
                               // current
Shinya Kitaoka 120a6e
    finalizeSelection();
Toshihiro Shimizu 890ddd
}