Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "plastictool.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzTools includes
Toshihiro Shimizu 890ddd
#include "tooloptionscontrols.h"
Toshihiro Shimizu 890ddd
#include "tools/toolcommandids.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzQt includes
Toshihiro Shimizu 890ddd
#include "toonzqt/selection.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/tselectionhandle.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/dvmimedata.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/dvdialog.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/selectioncommandids.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/tframehandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheethandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tobjecthandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tonionskinmaskhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobject.h"
Toshihiro Shimizu 890ddd
#include "toonz/doubleparamcmd.h"
Toshihiro Shimizu 890ddd
#include "toonz/palettecontroller.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsimplelevel.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzExt includes
Toshihiro Shimizu 890ddd
#include "ext/plasticskeleton.h"
Toshihiro Shimizu 890ddd
#include "ext/plasticdeformerstorage.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tgl.h"
Toshihiro Shimizu 890ddd
#include "tundo.h"
Toshihiro Shimizu 890ddd
#include "tfunctorinvoker.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qapplication></qapplication>
Toshihiro Shimizu 890ddd
#include <qstring></qstring>
Campbell Barton d0e335
#include <qtoolbar></qtoolbar>
Toshihiro Shimizu 890ddd
#include <qpushbutton></qpushbutton>
Toshihiro Shimizu 890ddd
#include <qlabel></qlabel>
Toshihiro Shimizu 890ddd
#include <qclipboard></qclipboard>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// tcg includes
Toshihiro Shimizu 890ddd
#include "tcg/tcg_macros.h"
Toshihiro Shimizu 890ddd
#include "tcg/tcg_point_ops.h"
Toshihiro Shimizu 890ddd
#include "tcg/tcg_list.h"
Toshihiro Shimizu 890ddd
#include "tcg/tcg_iterator_ops.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    Local namespace
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static const double l_dmax = (std::numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticToolLocals namespace
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace PlasticToolLocals;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace PlasticToolLocals {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticTool l_plasticTool;
Toshihiro Shimizu 890ddd
bool l_suspendParamsObservation = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPointD projection(const PlasticSkeleton &skeleton, int e, const TPointD &pos) {
Shinya Kitaoka 120a6e
  const PlasticSkeleton::edge_type &ed = skeleton.edge(e);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TPointD &p0 = skeleton.vertex(ed.vertex(0)).P();
Shinya Kitaoka 120a6e
  const TPointD &p1 = skeleton.vertex(ed.vertex(1)).P();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return tcg::point_ops::projection(pos, p0, tcg::point_ops::direction(p0, p1));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
double frame() {
Shinya Kitaoka 120a6e
  return TTool::getApplication()->getCurrentFrame()->getFrame();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int row() { return int(frame()) + 1; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int column() {
Shinya Kitaoka 120a6e
  return TTool::getApplication()->getCurrentColumn()->getColumnIndex();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void setCell(int row, int col) {
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  app->getCurrentFrame()->setCurrentFrame(row);
Shinya Kitaoka 120a6e
  app->getCurrentColumn()->setColumnIndex(col);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TXshColumn *xshColumn() {
Shinya Kitaoka 120a6e
  TXsheet *xsh = TTool::getApplication()->getCurrentXsheet()->getXsheet();
Shinya Kitaoka 120a6e
  return xsh->getColumn(column());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStageObject *stageObject() {
Shinya Kitaoka 120a6e
  TXsheet *xsh = TTool::getApplication()->getCurrentXsheet()->getXsheet();
Shinya Kitaoka 120a6e
  return xsh->getStageObject(TStageObjectId::ColumnId(column()));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const TXshCell &xshCell() {
Shinya Kitaoka 120a6e
  TXsheet *xsh = TTool::getApplication()->getCurrentXsheet()->getXsheet();
Shinya Kitaoka 120a6e
  return xsh->getCell(frame(), column());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int skeletonId() {
Shinya Kitaoka 120a6e
  TStageObject *obj                      = stageObject();
Shinya Kitaoka 120a6e
  const PlasticSkeletonDeformationP &def = obj->getPlasticSkeletonDeformation();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return def ? def->skeletonId(obj->paramsTime(frame()))
Shinya Kitaoka 120a6e
             : 1;  // 1 (not -1) is intended.
Shinya Kitaoka 120a6e
}  // Means '' (empty string)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double sdFrame() { return stageObject()->paramsTime(frame()); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void setKeyframe(TDoubleParamP ¶m, double frame) {
Shinya Kitaoka 120a6e
  if (!param->isKeyframe(frame)) {
Shinya Kitaoka 120a6e
    KeyframeSetter setter(param.getPointer(), -1,
Shinya Kitaoka 120a6e
                          false);  // Not placing undos through this setter
Shinya Kitaoka 120a6e
    setter.createKeyframe(frame);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void setKeyframe(SkVD *vd, double frame) {
Shinya Kitaoka 120a6e
  // vd->setKeyframe(frame);                          // Nope. In fact...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Keyframe set is performed with a special tool that is NOT AVAILABLE in
Shinya Kitaoka 120a6e
  // TnzExt
Shinya Kitaoka 120a6e
  // (thus, not available to m_sd). It deals with specifying the correct
Shinya Kitaoka 120a6e
  // interpolation
Shinya Kitaoka 120a6e
  // type (by user preference, which is TnzLib stuff), etc...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Traverse vd's parameters. In case they don't have a keyframe at current
Shinya Kitaoka 120a6e
  // frame, add one.
Shinya Kitaoka 120a6e
  for (int p = 0; p < SkVD::PARAMS_COUNT; ++p)
Shinya Kitaoka 120a6e
    setKeyframe(vd->m_params[p], frame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void setKeyframe(const PlasticSkeletonDeformationP &sd, double frame) {
Shinya Kitaoka 120a6e
  // NOTE: The skeleton ids parameter is NOT affected
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkD::vd_iterator vdt, vdEnd;
Shinya Kitaoka 120a6e
  sd->vertexDeformations(vdt, vdEnd);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (; vdt != vdEnd; ++vdt) setKeyframe((*vdt).second, frame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void invalidateXsheet() {
Shinya Kitaoka 120a6e
  TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  stageObject()->updateKeyframes();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  l_plasticTool.storeDeformation();
Shinya Kitaoka 120a6e
  l_plasticTool.invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace PlasticToolLocals
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    Mime  definitions
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
struct PlasticSkeletonPMime final : public DvMimeData {
Shinya Kitaoka 120a6e
  PlasticSkeletonP m_skeleton;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  PlasticSkeletonPMime(const PlasticSkeletonP &skeleton)
Shinya Kitaoka 120a6e
      : m_skeleton(skeleton) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  DvMimeData *clone() const override {
Shinya Kitaoka 120a6e
    return new PlasticSkeletonPMime(m_skeleton);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 473e70
Shinya Kitaoka 473e70
  void releaseData() override { m_skeleton = PlasticSkeletonP(); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
struct SkDPMime final : public DvMimeData {
Shinya Kitaoka 120a6e
  SkDP m_sd;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  SkDPMime(const SkDP &sd) : m_sd(sd) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  DvMimeData *clone() const override { return new SkDPMime(m_sd); }
Shinya Kitaoka 473e70
Shinya Kitaoka 473e70
  void releaseData() override { m_sd = SkDP(); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    Undo  definitions
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// NOTE: Some of the following UNDOs have complex and dynamic contents, and I
Shinya Kitaoka 120a6e
// don't want to
Shinya Kitaoka 120a6e
//       trace their size thoroughly. So, I'll follow this guideline: given the
Shinya Kitaoka 120a6e
//       standard
Shinya Kitaoka 120a6e
//       100 MB undos pool, how many undos of one specific type I'd want the
Shinya Kitaoka 120a6e
//       pool to be able
Toshihiro Shimizu 890ddd
//       to store?
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class SetVertexNameUndo final : public TUndo {
Shinya Kitaoka 120a6e
  int m_row, m_col;  //!< Xsheet coordinates
Shinya Kitaoka 120a6e
  int m_v;           //!< Changed vertex
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  mutable QString m_oldName, m_newName;  //!< Vertex names
Shinya Kitaoka 120a6e
  mutable SkVD
Shinya Kitaoka 120a6e
      m_oldVd;  //!< Old Vertex deformation (SHARE-OWNED, rather than CLONED)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  SetVertexNameUndo(int v, const QString &newName)
Shinya Kitaoka 120a6e
      : m_row(::row()), m_col(::column()), m_v(v), m_newName(newName) {
Shinya Kitaoka 120a6e
    const PlasticSkeletonP &skeleton = l_plasticTool.skeleton();
Shinya Kitaoka 120a6e
    const PlasticSkeletonVertex &vx  = skeleton->vertex(v);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_oldName = vx.name();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
  int getSize() const override {
Shinya Kitaoka 38fd86
    return sizeof(*this);
Shinya Kitaoka 38fd86
  }  // sizeof this is roughly ok
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void redo() const override {
Shinya Kitaoka 120a6e
    PlasticTool::TemporaryActivation tempActivate(m_row, m_col);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Store the vertex deformation before it's released (possibly destroyed)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      const SkDP &sd = l_plasticTool.deformation();
Shinya Kitaoka 120a6e
      TCG_ASSERT(sd, return );
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      const SkVD *vd = sd->vertexDeformation(m_oldName);
Shinya Kitaoka 120a6e
      TCG_ASSERT(vd, return );
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_oldVd = *vd;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (m_v >= 0) l_plasticTool.setSkeletonSelection(m_v);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    l_plasticTool.setVertexName(m_newName);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    ::invalidateXsheet();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void undo() const override {
Shinya Kitaoka 120a6e
    PlasticTool::TemporaryActivation tempActivate(m_row, m_col);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    const SkDP &sd = l_plasticTool.deformation();
Shinya Kitaoka 120a6e
    TCG_ASSERT(sd, return );
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (m_v >= 0) l_plasticTool.setSkeletonSelection(m_v);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    l_plasticTool.setVertexName(m_oldName);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Restore the vertex deformation.
Shinya Kitaoka 120a6e
    SkVD *vd = sd->vertexDeformation(m_oldName);
Shinya Kitaoka 120a6e
    assert(vd);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    *vd = m_oldVd;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    ::invalidateXsheet();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//========================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class PasteDeformationUndo final : public TUndo {
Shinya Kitaoka 120a6e
  int m_col;              //!< Affected column
Shinya Kitaoka 120a6e
  SkDP m_oldSd, m_newSd;  //!< The skeleton deformations
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  PasteDeformationUndo(const SkDP &newSd)
Shinya Kitaoka 120a6e
      : m_col(column())
Shinya Kitaoka 120a6e
      , m_oldSd(stageObject()->getPlasticSkeletonDeformation())
Shinya Kitaoka 120a6e
      , m_newSd(newSd) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  int getSize() const override { return 1 << 20; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void redo() const override {
Shinya Kitaoka 120a6e
    TTool::getApplication()->getCurrentColumn()->setColumnIndex(m_col);
Shinya Kitaoka 120a6e
    stageObject()->setPlasticSkeletonDeformation(m_newSd);
Shinya Kitaoka 120a6e
    ::invalidateXsheet();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void undo() const override {
Shinya Kitaoka 120a6e
    TTool::getApplication()->getCurrentColumn()->setColumnIndex(m_col);
Shinya Kitaoka 120a6e
    stageObject()->setPlasticSkeletonDeformation(m_oldSd);
Shinya Kitaoka 120a6e
    ::invalidateXsheet();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticTool::TemporaryActivation  implementation
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticTool::TemporaryActivation::TemporaryActivation(int row, int col)
Shinya Kitaoka 120a6e
    : m_activate(!l_plasticTool.isActive()) {
Shinya Kitaoka 120a6e
  if (m_activate) l_plasticTool.onActivate();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ::setCell(row, col);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticTool::TemporaryActivation::~TemporaryActivation() {
Shinya Kitaoka 120a6e
  if (m_activate) l_plasticTool.onDeactivate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticToolOptionsBox::SkelIdComboBox  definition
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class PlasticToolOptionsBox::SkelIdsComboBox final : public QComboBox {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  SkelIdsComboBox(QWidget *parent = 0) : QComboBox(parent) {
Shinya Kitaoka 120a6e
    updateSkeletonsList();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void updateSkeletonsList();
Shinya Kitaoka 120a6e
  void updateCurrentSkeleton();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticToolOptionsBox::SkelIdsComboBox::updateSkeletonsList() {
Shinya Kitaoka 120a6e
  clear();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const SkDP &sd = l_plasticTool.deformation();
Shinya Kitaoka 120a6e
  if (!sd) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QStringList skeletonsList;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkD::skelId_iterator st, sEnd;
Shinya Kitaoka 120a6e
  sd->skeletonIds(st, sEnd);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (; st != sEnd; ++st) skeletonsList.push_back(QString::number(*st));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QComboBox::insertItems(0, skeletonsList);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  updateCurrentSkeleton();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticToolOptionsBox::SkelIdsComboBox::updateCurrentSkeleton() {
Shinya Kitaoka 120a6e
  setCurrentIndex(findText(QString::number(::skeletonId())));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticToolOptionsBox  implementation
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticToolOptionsBox::PlasticToolOptionsBox(QWidget *parent, TTool *tool,
shun_iwasawa eaa9f3
                                             TPaletteHandle *pltHandle,
shun_iwasawa eaa9f3
                                             ToolHandle *toolHandle)
shun_iwasawa eaa9f3
    : GenericToolOptionsBox(parent, tool, pltHandle, PlasticTool::MODES_COUNT,
shun_iwasawa eaa9f3
                            toolHandle)
Shinya Kitaoka 120a6e
    , m_tool(tool)
Shinya Kitaoka 120a6e
    , m_subToolbars(new GenericToolOptionsBox *[PlasticTool::MODES_COUNT])
Toshihiro Shimizu 890ddd
//, m_subToolbarActions(new QAction*[PlasticTool::MODES_COUNT])
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
  struct locals {
Shinya Kitaoka 120a6e
    static inline QWidget *newSpace(QWidget *parent = 0) {
Shinya Kitaoka 120a6e
      QWidget *space = new QWidget(parent);
Shinya Kitaoka 120a6e
      space->setFixedWidth(TOOL_OPTIONS_LEFT_MARGIN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      return space;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  };
Jeremy Bullock ed3888
  setObjectName("toolOptionsPanel");
Shinya Kitaoka 120a6e
  // Create Mesh button
Shinya Kitaoka 120a6e
  QPushButton *meshifyButton = new QPushButton(tr("Create Mesh"));
Jeremy Bullock ed3888
Shinya Kitaoka 120a6e
  // Add skeleton id-related widgets
Shinya Kitaoka 120a6e
  QLabel *skelIdLabel = new QLabel(tr("Skeleton:"));
Shinya Kitaoka 120a6e
  m_skelIdComboBox    = new SkelIdsComboBox;
Shinya Kitaoka 120a6e
  m_addSkelButton     = new QPushButton("+");  // Connected in the show event
Shinya Kitaoka 120a6e
  m_removeSkelButton  = new QPushButton("-");  // Connected in the show event
Shinya Kitaoka 120a6e
  // Add sub-options for each mode group
Jeremy Bullock ed3888
  for (int m = 0; m != PlasticTool::MODES_COUNT; ++m)
Jeremy Bullock ed3888
    m_subToolbars[m] =
Jeremy Bullock ed3888
        new GenericToolOptionsBox(0, tool, pltHandle, m, 0, false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  meshifyButton->setFixedHeight(20);
Jeremy Bullock ed3888
  int buttonWidth = fontMetrics().width(meshifyButton->text()) + 20;
Jeremy Bullock ed3888
  meshifyButton->setFixedWidth(buttonWidth);
Shinya Kitaoka 120a6e
  QAction *meshifyAction =
Shinya Kitaoka 120a6e
      CommandManager::instance()->getAction("A_ToolOption_Meshify");
Shinya Kitaoka 120a6e
  meshifyButton->addAction(meshifyAction);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  skelIdLabel->setFixedHeight(20);
Shinya Kitaoka 120a6e
  m_skelIdComboBox->setFixedWidth(50);
Shinya Kitaoka 120a6e
  m_addSkelButton->setFixedSize(20, 20);
Shinya Kitaoka 120a6e
  m_removeSkelButton->setFixedSize(20, 20);
Shinya Kitaoka 120a6e
  for (int m = 0; m != PlasticTool::MODES_COUNT; ++m)
Shinya Kitaoka 120a6e
    m_subToolbars[m]->setContentsMargins(0, 0, 0, 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*- Layout -*/
Shinya Kitaoka 120a6e
  // Add created widgets to the toolbar (in reverse order since we're inserting
Shinya Kitaoka 120a6e
  // at 0)
Shinya Kitaoka 120a6e
  m_layout->insertWidget(0, m_removeSkelButton);
Shinya Kitaoka 120a6e
  m_layout->insertWidget(0, m_addSkelButton);
Shinya Kitaoka 120a6e
  m_layout->insertWidget(0, m_skelIdComboBox);
Shinya Kitaoka 120a6e
  m_layout->insertWidget(0, skelIdLabel);
Shinya Kitaoka 120a6e
  m_layout->insertWidget(0, locals::newSpace(this));
Shinya Kitaoka 120a6e
  m_layout->insertWidget(0, meshifyButton);
Shinya Kitaoka 120a6e
  m_layout->insertWidget(0, locals::newSpace(this));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (int m = 0; m != PlasticTool::MODES_COUNT; ++m)
Shinya Kitaoka 120a6e
    m_layout->insertWidget(m_layout->count() - 1, m_subToolbars[m], 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool ret = true;
Shinya Kitaoka 120a6e
  ret      = ret && connect(meshifyButton, SIGNAL(clicked()), meshifyAction,
Shinya Kitaoka 120a6e
                       SLOT(trigger()));
Shinya Kitaoka 120a6e
  assert(ret);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Add Animation mode fields corresponding to vertex properties
Shinya Kitaoka 120a6e
  GenericToolOptionsBox *animateOptionsBox =
Shinya Kitaoka 120a6e
      m_subToolbars[PlasticTool::ANIMATE_IDX];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Adjust some specific controls first
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    ToolOptionTextField *minAngleField = static_cast<tooloptiontextfield *="">(</tooloptiontextfield>
Shinya Kitaoka 120a6e
        animateOptionsBox->control("minAngle"));
Shinya Kitaoka 120a6e
    assert(minAngleField);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    minAngleField->setFixedWidth(40);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    ToolOptionTextField *maxAngleField = static_cast<tooloptiontextfield *="">(</tooloptiontextfield>
Shinya Kitaoka 120a6e
        animateOptionsBox->control("maxAngle"));
Shinya Kitaoka 120a6e
    assert(maxAngleField);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    maxAngleField->setFixedWidth(40);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Distance
Shinya Kitaoka 120a6e
  ToolOptionParamRelayField *distanceField = new ToolOptionParamRelayField(
Shinya Kitaoka 120a6e
      &l_plasticTool, &l_plasticTool.m_distanceRelay);
Shinya Kitaoka 120a6e
  distanceField->setGlobalKey(&l_plasticTool.m_globalKey,
Shinya Kitaoka 120a6e
                              &l_plasticTool.m_relayGroup);
Toshihiro Shimizu 890ddd
Jeremy Bullock 771290
  ClickableLabel *distanceLabel = new ClickableLabel(tr("Distance"));
Shinya Kitaoka 120a6e
  distanceLabel->setFixedHeight(20);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Angle
Shinya Kitaoka 120a6e
  ToolOptionParamRelayField *angleField = new ToolOptionParamRelayField(
Shinya Kitaoka 120a6e
      &l_plasticTool, &l_plasticTool.m_angleRelay);
Shinya Kitaoka 120a6e
  angleField->setGlobalKey(&l_plasticTool.m_globalKey,
Shinya Kitaoka 120a6e
                           &l_plasticTool.m_relayGroup);
Toshihiro Shimizu 890ddd
Jeremy Bullock 771290
  ClickableLabel *angleLabel = new ClickableLabel(tr("Angle"));
Shinya Kitaoka 120a6e
  angleLabel->setFixedHeight(20);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // SO
Shinya Kitaoka 120a6e
  ToolOptionParamRelayField *soField =
Shinya Kitaoka 120a6e
      new ToolOptionParamRelayField(&l_plasticTool, &l_plasticTool.m_soRelay);
Shinya Kitaoka 120a6e
  soField->setGlobalKey(&l_plasticTool.m_globalKey,
Shinya Kitaoka 120a6e
                        &l_plasticTool.m_relayGroup);
Toshihiro Shimizu 890ddd
Jeremy Bullock 771290
  ClickableLabel *soLabel = new ClickableLabel(tr("SO"));
Shinya Kitaoka 120a6e
  soLabel->setFixedHeight(20);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QHBoxLayout *animateLayout = animateOptionsBox->hLayout();
Shinya Kitaoka 120a6e
  animateLayout->insertWidget(0, soField);
Shinya Kitaoka 120a6e
  animateLayout->insertWidget(0, soLabel);
Shinya Kitaoka 120a6e
  animateLayout->insertWidget(0, angleField);
Shinya Kitaoka 120a6e
  animateLayout->insertWidget(0, angleLabel);
Shinya Kitaoka 120a6e
  animateLayout->insertWidget(0, distanceField);
Shinya Kitaoka 120a6e
  animateLayout->insertWidget(0, distanceLabel);
Shinya Kitaoka 120a6e
Jeremy Bullock 771290
  ret = ret && connect(distanceLabel, SIGNAL(onMousePress(QMouseEvent *)),
Jeremy Bullock 771290
                       distanceField, SLOT(receiveMousePress(QMouseEvent *)));
Jeremy Bullock 771290
  ret = ret && connect(distanceLabel, SIGNAL(onMouseMove(QMouseEvent *)),
Jeremy Bullock 771290
                       distanceField, SLOT(receiveMouseMove(QMouseEvent *)));
Jeremy Bullock 771290
  ret = ret && connect(distanceLabel, SIGNAL(onMouseRelease(QMouseEvent *)),
Jeremy Bullock 771290
                       distanceField, SLOT(receiveMouseRelease(QMouseEvent *)));
Jeremy Bullock 771290
  ret = ret && connect(angleLabel, SIGNAL(onMousePress(QMouseEvent *)),
Jeremy Bullock 771290
                       angleField, SLOT(receiveMousePress(QMouseEvent *)));
Jeremy Bullock 771290
  ret = ret && connect(angleLabel, SIGNAL(onMouseMove(QMouseEvent *)),
Jeremy Bullock 771290
                       angleField, SLOT(receiveMouseMove(QMouseEvent *)));
Jeremy Bullock 771290
  ret = ret && connect(angleLabel, SIGNAL(onMouseRelease(QMouseEvent *)),
Jeremy Bullock 771290
                       angleField, SLOT(receiveMouseRelease(QMouseEvent *)));
Jeremy Bullock 771290
  ret = ret && connect(soLabel, SIGNAL(onMousePress(QMouseEvent *)), soField,
Jeremy Bullock 771290
                       SLOT(receiveMousePress(QMouseEvent *)));
Jeremy Bullock 771290
  ret = ret && connect(soLabel, SIGNAL(onMouseMove(QMouseEvent *)), soField,
Jeremy Bullock 771290
                       SLOT(receiveMouseMove(QMouseEvent *)));
Jeremy Bullock 771290
  ret = ret && connect(soLabel, SIGNAL(onMouseRelease(QMouseEvent *)), soField,
Jeremy Bullock 771290
                       SLOT(receiveMouseRelease(QMouseEvent *)));
Jeremy Bullock 771290
  assert(ret);
Jeremy Bullock 771290
Shinya Kitaoka 120a6e
  onPropertyChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticToolOptionsBox::showEvent(QShowEvent *se) {
Shinya Kitaoka 120a6e
  bool ret = true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ret = ret && connect(&l_plasticTool, SIGNAL(skelIdsListChanged()),
Shinya Kitaoka 120a6e
                       SLOT(onSkelIdsListChanged()));
Shinya Kitaoka 120a6e
  ret = ret && connect(&l_plasticTool, SIGNAL(skelIdChanged()),
Shinya Kitaoka 120a6e
                       SLOT(onSkelIdChanged()));
Shinya Kitaoka 120a6e
  ret = ret && connect(m_skelIdComboBox, SIGNAL(activated(int)),
Shinya Kitaoka 120a6e
                       SLOT(onSkelIdEdited()));
Shinya Kitaoka 120a6e
  ret = ret &&
Shinya Kitaoka 120a6e
        connect(m_addSkelButton, SIGNAL(released()), SLOT(onAddSkeleton()));
Shinya Kitaoka 120a6e
  ret = ret && connect(m_removeSkelButton, SIGNAL(released()),
Shinya Kitaoka 120a6e
                       SLOT(onRemoveSkeleton()));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(ret);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_skelIdComboBox->updateSkeletonsList();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticToolOptionsBox::hideEvent(QHideEvent *he) {
Shinya Kitaoka 120a6e
  disconnect(&l_plasticTool, 0, this, 0);
Shinya Kitaoka 120a6e
  disconnect(m_skelIdComboBox, 0, this, 0);
Shinya Kitaoka 120a6e
  disconnect(m_addSkelButton, 0, this, 0);
Shinya Kitaoka 120a6e
  disconnect(m_removeSkelButton, 0, this, 0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticToolOptionsBox::onPropertyChanged() {
Shinya Kitaoka 120a6e
  // Fetch current mode index
Shinya Kitaoka 120a6e
  TPropertyGroup *pGroup = m_tool->getProperties(PlasticTool::MODES_COUNT);
Shinya Kitaoka 120a6e
  assert(pGroup);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TEnumProperty *prop =
Shinya Kitaoka 120a6e
      dynamic_cast<tenumproperty *="">(pGroup->getProperty("mode"));</tenumproperty>
Shinya Kitaoka 120a6e
  assert(prop);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int mode = prop->getIndex();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Show the specified mode options, hide all the others
Shinya Kitaoka 120a6e
  for (int m = 0; m != PlasticTool::MODES_COUNT; ++m)
Shinya Kitaoka 120a6e
    m_subToolbars[m]->setVisible(m == mode);
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticToolOptionsBox::onSkelIdsListChanged() {
Shinya Kitaoka 120a6e
  m_skelIdComboBox->updateSkeletonsList();
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticToolOptionsBox::onSkelIdChanged() {
Shinya Kitaoka 120a6e
  m_skelIdComboBox->updateCurrentSkeleton();
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticToolOptionsBox::onSkelIdEdited() {
Shinya Kitaoka 120a6e
  int skelId = m_skelIdComboBox->currentText().toInt();
Shinya Kitaoka 120a6e
  if (skelId == ::skeletonId()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!l_plasticTool.deformation()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  l_plasticTool.editSkelId_undo(skelId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticToolOptionsBox::onAddSkeleton() {
Shinya Kitaoka 120a6e
  if (l_plasticTool.isEnabled())
Shinya Kitaoka 120a6e
    l_plasticTool.addSkeleton_undo(new PlasticSkeleton);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticToolOptionsBox::onRemoveSkeleton() {
Shinya Kitaoka 120a6e
  if (l_plasticTool.isEnabled() && l_plasticTool.deformation())
Shinya Kitaoka 120a6e
    l_plasticTool.removeSkeleton_withKeyframes_undo(::skeletonId());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//****************************************************************************************
Shinya Kitaoka 120a6e
//    PlasticTool  implementation
Shinya Kitaoka 120a6e
//****************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticTool::PlasticTool()
Shinya Kitaoka 120a6e
    : TTool(T_Plastic)
Shinya Kitaoka 120a6e
    , m_skelId(-(std::numeric_limits<int>::max)())</int>
Shinya Kitaoka 120a6e
    , m_propGroup(new TPropertyGroup[MODES_COUNT + 1])
Shinya Kitaoka 120a6e
    , m_mode("mode")
Shinya Kitaoka 120a6e
    , m_vertexName("vertexName", L"")
Shinya Kitaoka 120a6e
    , m_interpolate("interpolate", false)
Shinya Kitaoka 120a6e
    , m_snapToMesh("snapToMesh", false)
Shinya Kitaoka 120a6e
    , m_thickness("Thickness", 1, 100, 5)
Shinya Kitaoka 120a6e
    , m_rigidValue("rigidValue")
Shinya Kitaoka 120a6e
    , m_globalKey("globalKeyframe", true)
Shinya Kitaoka 120a6e
    , m_keepDistance("keepDistance", true)
Shinya Kitaoka 120a6e
    , m_minAngle("minAngle", L"")
Shinya Kitaoka 120a6e
    , m_maxAngle("maxAngle", L"")
Shinya Kitaoka 120a6e
    , m_distanceRelay("distanceRelay")
Shinya Kitaoka 120a6e
    , m_angleRelay("angleRelay")
Shinya Kitaoka 120a6e
    , m_soRelay("soRelay")
Shinya Kitaoka 120a6e
    , m_skelIdRelay("skelIdRelay")
Shinya Kitaoka 120a6e
    , m_pressedPos(TConsts::napd)
Shinya Kitaoka 120a6e
    , m_dragged(false)
Shinya Kitaoka 120a6e
    , m_svHigh(-1)
Shinya Kitaoka 120a6e
    , m_seHigh(-1)
Shinya Kitaoka 120a6e
    , m_mvHigh(-1)
Shinya Kitaoka 120a6e
    , m_meHigh(-1)
Shinya Kitaoka 120a6e
    , m_rigidityPainter(createRigidityPainter())
Shinya Kitaoka 120a6e
    , m_showSkeletonOS(true)
Shinya Kitaoka 120a6e
    , m_recompileOnMouseRelease(false) {
Shinya Kitaoka 120a6e
  // And now, a little trick about tool binding
Shinya Kitaoka 120a6e
  bind(TTool::AllImages);   // Attach the tool to all types :)
Shinya Kitaoka 120a6e
  bind(TTool::MeshLevels);  // But disable it for all but meshes :0
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // This little trick is needed to associate the tool to common levels (the
Shinya Kitaoka 120a6e
  // toolbar must appear), in
Shinya Kitaoka 120a6e
  // order to make them meshable.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Bind properties to the appropriate property group (needed by the automatic
Shinya Kitaoka 120a6e
  // toolbar builder)
Shinya Kitaoka 120a6e
  m_propGroup[MODES_COUNT].bind(m_mode);
Shinya Kitaoka 120a6e
  m_propGroup[MODES_COUNT].bind(m_vertexName);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_propGroup[RIGIDITY_IDX].bind(m_thickness);
Shinya Kitaoka 120a6e
  m_propGroup[RIGIDITY_IDX].bind(m_rigidValue);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_propGroup[BUILD_IDX].bind(m_interpolate);
Shinya Kitaoka 120a6e
  m_propGroup[BUILD_IDX].bind(m_snapToMesh);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_propGroup[ANIMATE_IDX].bind(m_globalKey);
Shinya Kitaoka 120a6e
  m_propGroup[ANIMATE_IDX].bind(m_keepDistance);
Shinya Kitaoka 120a6e
  m_propGroup[ANIMATE_IDX].bind(m_minAngle);
Shinya Kitaoka 120a6e
  m_propGroup[ANIMATE_IDX].bind(m_maxAngle);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_relayGroup.bind(m_distanceRelay);
Shinya Kitaoka 120a6e
  m_relayGroup.bind(m_angleRelay);
Shinya Kitaoka 120a6e
  m_relayGroup.bind(m_soRelay);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_mode.setId("SkeletonMode");
Shinya Kitaoka 120a6e
  m_vertexName.setId("VertexName");
Shinya Kitaoka 120a6e
  m_interpolate.setId("Interpolate");
Shinya Kitaoka 120a6e
  m_snapToMesh.setId("SnapToMesh");
Shinya Kitaoka 120a6e
  m_thickness.setId("Thickness");
Shinya Kitaoka 120a6e
  m_rigidValue.setId("RigidValue");
Shinya Kitaoka 120a6e
  m_globalKey.setId("GlobalKey");
Shinya Kitaoka 120a6e
  m_keepDistance.setId("KeepDistance");
Shinya Kitaoka 120a6e
  m_minAngle.setId("MinAngle");
Shinya Kitaoka 120a6e
  m_maxAngle.setId("MaxAngle");
Shinya Kitaoka 120a6e
  m_distanceRelay.setId("DistanceRelay");
Shinya Kitaoka 120a6e
  m_angleRelay.setId("AngleRelay");
Shinya Kitaoka 120a6e
  m_soRelay.setId("SoRelay");
Shinya Kitaoka 120a6e
  m_skelIdRelay.setId("SkelIdRelay");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Attach to selections
Shinya Kitaoka 120a6e
  m_svSel.setView(this);
Shinya Kitaoka 120a6e
  m_mvSel.setView(this), m_meSel.setView(this);
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
PlasticTool::~PlasticTool() {
Shinya Kitaoka 120a6e
  if (m_sd) m_sd->removeObserver(this);
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
TTool::ToolType PlasticTool::getToolType() const {
Shinya Kitaoka 120a6e
  switch (m_mode.getIndex()) {
Shinya Kitaoka 120a6e
  case MESH_IDX:
Shinya Kitaoka 120a6e
  case RIGIDITY_IDX:
Shinya Kitaoka 120a6e
    return TTool::LevelWriteTool;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  case BUILD_IDX:
Shinya Kitaoka 120a6e
  case ANIMATE_IDX:
Shinya Kitaoka 120a6e
    return TTool::ColumnTool;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(false);
Shinya Kitaoka 120a6e
  return TTool::GenericTool;
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
void PlasticTool::updateTranslation() {
Shinya Kitaoka 120a6e
  m_mode.setQStringName(tr("Mode:"));
Shinya Kitaoka 120a6e
  m_mode.deleteAllValues();
Shinya Kitaoka 120a6e
  m_mode.addValue(tr("Edit Mesh").toStdWString());
Shinya Kitaoka 120a6e
  m_mode.addValue(tr("Paint Rigid").toStdWString());
Shinya Kitaoka 120a6e
  m_mode.addValue(tr("Build Skeleton").toStdWString());
Shinya Kitaoka 120a6e
  m_mode.addValue(tr("Animate").toStdWString());
Shinya Kitaoka 120a6e
  m_mode.setIndex(BUILD_IDX);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_vertexName.setQStringName(tr("Vertex Name:"));
Shinya Kitaoka 120a6e
  m_interpolate.setQStringName(tr("Allow Stretching"));
Shinya Kitaoka 120a6e
  m_snapToMesh.setQStringName(tr("Snap To Mesh"));
Shinya Kitaoka 120a6e
  m_thickness.setQStringName(tr("Thickness"));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_rigidValue.setQStringName("");
Shinya Kitaoka 120a6e
  m_rigidValue.deleteAllValues();
Shinya Kitaoka 120a6e
  m_rigidValue.addValue(tr("Rigid").toStdWString());
Shinya Kitaoka 120a6e
  m_rigidValue.addValue(tr("Flex").toStdWString());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_globalKey.setQStringName(tr("Global Key"));
Shinya Kitaoka 120a6e
  m_keepDistance.setQStringName(tr("Keep Distance"));
Shinya Kitaoka 120a6e
  m_minAngle.setQStringName(tr("Angle Bounds"));
Shinya Kitaoka 120a6e
  m_maxAngle.setQStringName("");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ToolOptionsBox *PlasticTool::createOptionsBox() {
Shinya Kitaoka 120a6e
  // Create the options box
Shinya Kitaoka 120a6e
  TPaletteHandle *currPalette =
Shinya Kitaoka 120a6e
      TTool::getApplication()->getPaletteController()->getCurrentLevelPalette();
shun_iwasawa eaa9f3
  ToolHandle *currTool = m_application->getCurrentTool();
Shinya Kitaoka 120a6e
  PlasticToolOptionsBox *optionsBox =
shun_iwasawa eaa9f3
      new PlasticToolOptionsBox(0, this, currPalette, currTool);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Connect it to receive m_mode notifications
Shinya Kitaoka 120a6e
  m_mode.addListener(optionsBox);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return optionsBox;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeletonP PlasticTool::skeleton() const {
Shinya Kitaoka 120a6e
  return m_sd ? m_sd->skeleton(::sdFrame()) : PlasticSkeletonP();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeleton &PlasticTool::deformedSkeleton() {
otakuto 91a93e
  return m_deformedSkeleton([this](PlasticSkeleton &deformedSkeleton) {
otakuto 91a93e
    updateDeformedSkeleton(deformedSkeleton);
otakuto 91a93e
  });
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::touchSkeleton() {
Shinya Kitaoka 120a6e
  touchDeformation();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int skelId = ::skeletonId();
Shinya Kitaoka 120a6e
  if (!m_sd->skeleton(skelId)) {
Shinya Kitaoka 120a6e
    m_sd->attach(skelId, new PlasticSkeleton);
Shinya Kitaoka 120a6e
    emit skelIdsListChanged();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::touchDeformation() {
Shinya Kitaoka 120a6e
  if (m_sd) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Store a new deformation in the column's stage object
Shinya Kitaoka 120a6e
  stageObject()->setPlasticSkeletonDeformation(new PlasticSkeletonDeformation);
Shinya Kitaoka 120a6e
  storeDeformation();  // Builds the deformed skeleton too
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::storeDeformation() {
Shinya Kitaoka 120a6e
  const SkDP &sd = stageObject()->getPlasticSkeletonDeformation();
Shinya Kitaoka 120a6e
  if (m_sd != sd) {
Shinya Kitaoka 120a6e
    clearSkeletonSelections();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (m_sd) {
Shinya Kitaoka 120a6e
      m_sd->removeObserver(this);
Shinya Kitaoka 120a6e
      m_skelIdRelay.setParam(TDoubleParamP());
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Store the deformation, retrieving it from current column stage object
Shinya Kitaoka 120a6e
    m_sd = sd;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (m_sd) {
Shinya Kitaoka 120a6e
      m_sd->addObserver(this);
Shinya Kitaoka 120a6e
      m_skelIdRelay.setParam(m_sd->skeletonIdsParam());
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_skelIdRelay.notifyListeners();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  storeSkeletonId();
Shinya Kitaoka 120a6e
  if (m_mode.getIndex() == ANIMATE_IDX)
Shinya Kitaoka 120a6e
    m_deformedSkeleton.invalidate();  // Store the deformed skeleton too
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  emit skelIdsListChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::storeSkeletonId() {
Shinya Kitaoka 120a6e
  int skelId = m_sd ? m_sd->skeletonIdsParam()->getValue(::sdFrame())
Shinya Kitaoka 120a6e
                    : -(std::numeric_limits<int>::max)();</int>
Shinya Kitaoka 120a6e
  if (m_skelId != skelId) {
Shinya Kitaoka 120a6e
    m_skelId = skelId;
Shinya Kitaoka 120a6e
    clearSkeletonSelections();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    emit skelIdChanged();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::updateDeformedSkeleton(PlasticSkeleton &deformedSkeleton) {
Shinya Kitaoka 120a6e
  if (m_sd)
Shinya Kitaoka 120a6e
    m_sd->storeDeformedSkeleton(::skeletonId(), ::sdFrame(), deformedSkeleton);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    deformedSkeleton.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::onFrameSwitched() {
Shinya Kitaoka 120a6e
  storeSkeletonId();
Shinya Kitaoka 120a6e
  storeMeshImage();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  switch (m_mode.getIndex()) {
Shinya Kitaoka 120a6e
  case ANIMATE_IDX:
Shinya Kitaoka 120a6e
    m_deformedSkeleton.invalidate();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Update the relays' current frame
Shinya Kitaoka 120a6e
  double frame = ::sdFrame();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_distanceRelay.frame() = frame;
Shinya Kitaoka 120a6e
  m_angleRelay.frame()    = frame;
Shinya Kitaoka 120a6e
  m_soRelay.frame()       = frame;
Shinya Kitaoka 120a6e
  m_skelIdRelay.frame()   = frame;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_distanceRelay.notifyListeners();
Shinya Kitaoka 120a6e
  m_angleRelay.notifyListeners();
Shinya Kitaoka 120a6e
  m_soRelay.notifyListeners();
Shinya Kitaoka 120a6e
  m_skelIdRelay.notifyListeners();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::onColumnSwitched() {
Shinya Kitaoka 120a6e
  switch (m_mode.getIndex()) {
Shinya Kitaoka 120a6e
  case MESH_IDX:
Shinya Kitaoka 120a6e
  case BUILD_IDX:
Shinya Kitaoka 120a6e
  case RIGIDITY_IDX:
Shinya Kitaoka 120a6e
    m_pvs.m_showOriginalColumn = xshColumn();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  storeDeformation();
Shinya Kitaoka 120a6e
  storeMeshImage();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::onXsheetChanged() {
Shinya Kitaoka 120a6e
  onColumnSwitched();
Shinya Kitaoka 120a6e
  TTool::updateEnabled();  // Current cell may no longer be a mesh one (or
Shinya Kitaoka 120a6e
                           // viceversa),
Shinya Kitaoka 120a6e
}  // so tool enabled status must be updated.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::onChange() {
Shinya Kitaoka 120a6e
  // Since parameters are typically coupled, we could pass multiple, consecutive
Shinya Kitaoka 120a6e
  // times in
Shinya Kitaoka 120a6e
  // this notification function. We have to employ counter-measures to prevent
Shinya Kitaoka 120a6e
  // multiple
Shinya Kitaoka 120a6e
  // calls from affecting performance.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  static bool refresh = false;  // Accessible from locals since static
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  struct locals {
Shinya Kitaoka d1f6c4
    struct RefreshFunctor final : public TFunctorInvoker::BaseFunctor {
Shinya Kitaoka 473e70
      void operator()() override {
Shinya Kitaoka 120a6e
        refresh = false;
Shinya Kitaoka 120a6e
        l_plasticTool.storeSkeletonId();  // Calls ::sdFrame()
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        // This is needed to repaint the xsheet (not automatic otherwise)
Shinya Kitaoka 120a6e
        TTool::getApplication()->getCurrentObject()->notifyObjectIdChanged(
Shinya Kitaoka 120a6e
            false);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    };
Shinya Kitaoka 120a6e
  };  // locals
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Using invalidate/update and delayed invocation to prevent multiple calls to
Shinya Kitaoka 120a6e
  // ::sdFrame()
Shinya Kitaoka 120a6e
  m_deformedSkeleton.invalidate();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!refresh) {
Shinya Kitaoka 120a6e
    refresh = true;
Shinya Kitaoka 120a6e
    QMetaObject::invokeMethod(TFunctorInvoker::instance(), "invoke",
Shinya Kitaoka 120a6e
                              Qt::QueuedConnection,
Shinya Kitaoka 120a6e
                              Q_ARG(void *, new locals::RefreshFunctor));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Passing through Qt's event system to compress repaints in a single one
Shinya Kitaoka 120a6e
  TTool::Viewer *viewer = getViewer();
Shinya Kitaoka 120a6e
  if (viewer)                 // This goes through paintEvent(),
Shinya Kitaoka 120a6e
    viewer->invalidateAll();  // \a unlike TTool::invalidate()
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::onChange(const TParamChange &pc) {
Shinya Kitaoka 120a6e
  if (l_suspendParamsObservation) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  onChange();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::onSetViewer() {
Shinya Kitaoka 120a6e
  Viewer *viewer = getViewer();
Shinya Kitaoka 120a6e
  if (viewer) {
Shinya Kitaoka 120a6e
    PlasticVisualSettings &pvs =
Shinya Kitaoka 120a6e
        viewer->visualSettings().m_plasticVisualSettings;
Shinya Kitaoka 120a6e
    pvs = m_pvs;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Force options if needed
Shinya Kitaoka 120a6e
    if (m_mode.getIndex() == RIGIDITY_IDX) pvs.m_drawRigidity = true;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::onActivate() {
Shinya Kitaoka 120a6e
  bool ret;
Shinya Kitaoka 120a6e
  ret = connect(TTool::m_application->getCurrentFrame(),
Shinya Kitaoka 120a6e
                SIGNAL(frameSwitched()), this, SLOT(onFrameSwitched())),
Shinya Kitaoka 120a6e
  assert(ret);
Shinya Kitaoka 120a6e
  ret = connect(TTool::m_application->getCurrentColumn(),
Shinya Kitaoka 120a6e
                SIGNAL(columnIndexSwitched()), this, SLOT(onColumnSwitched())),
Shinya Kitaoka 120a6e
  assert(ret);
Shinya Kitaoka 120a6e
  ret = connect(TTool::m_application->getCurrentXsheet(),
Shinya Kitaoka 120a6e
                SIGNAL(xsheetChanged()), this, SLOT(onXsheetChanged())),
Shinya Kitaoka 120a6e
  assert(ret);
Shinya Kitaoka 120a6e
  ret = connect(TTool::m_application->getCurrentXsheet(),
Shinya Kitaoka 120a6e
                SIGNAL(xsheetSwitched()), this, SLOT(onXsheetChanged())),
Shinya Kitaoka 120a6e
  assert(ret);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  onSetViewer();
Shinya Kitaoka 120a6e
  onColumnSwitched();
Shinya Kitaoka 120a6e
  onFrameSwitched();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  setActive(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::onDeactivate() {
Shinya Kitaoka 120a6e
  setActive(false);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool ret;
Shinya Kitaoka 120a6e
  ret = disconnect(TTool::m_application->getCurrentFrame(),
Shinya Kitaoka 120a6e
                   SIGNAL(frameSwitched()), this, SLOT(onFrameSwitched())),
Shinya Kitaoka 120a6e
  assert(ret);
Shinya Kitaoka 120a6e
  ret =
Shinya Kitaoka 120a6e
      disconnect(TTool::m_application->getCurrentColumn(),
Shinya Kitaoka 120a6e
                 SIGNAL(columnIndexSwitched()), this, SLOT(onColumnSwitched())),
Shinya Kitaoka 120a6e
  assert(ret);
Shinya Kitaoka 120a6e
  ret = disconnect(TTool::m_application->getCurrentXsheet(),
Shinya Kitaoka 120a6e
                   SIGNAL(xsheetChanged()), this, SLOT(onXsheetChanged())),
Shinya Kitaoka 120a6e
  assert(ret);
Shinya Kitaoka 120a6e
  ret = disconnect(TTool::m_application->getCurrentXsheet(),
Shinya Kitaoka 120a6e
                   SIGNAL(xsheetSwitched()), this, SLOT(onXsheetChanged())),
Shinya Kitaoka 120a6e
  assert(ret);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Viewer *viewer = getViewer();
shun-iwasawa f20cae
  if (viewer) {
Shinya Kitaoka 120a6e
    viewer->visualSettings().m_plasticVisualSettings = PlasticVisualSettings();
shun-iwasawa f20cae
    // Only the mesh visibility is not reset in order to enable to keep the mesh
shun-iwasawa f20cae
    // hidden while using other tools
shun-iwasawa f20cae
    viewer->visualSettings().m_plasticVisualSettings.m_drawMeshesWireframe =
shun-iwasawa f20cae
        m_pvs.m_drawMeshesWireframe;
shun-iwasawa f20cae
  }
Shinya Kitaoka 120a6e
  m_sd = PlasticSkeletonDeformationP();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::onEnter() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::onLeave() {
Shinya Kitaoka 120a6e
  // Clear visualization vars
Shinya Kitaoka 120a6e
  m_pos    = TConsts::napd;
Shinya Kitaoka 120a6e
  m_svHigh = m_seHigh = -1;
Shinya Kitaoka 120a6e
  m_mvHigh = m_meHigh = MeshIndex();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::onSelectionChanged() {
Shinya Kitaoka 120a6e
  SkVD *vd = 0;
Shinya Kitaoka 120a6e
  if (m_sd && m_svSel.hasSingleObject()) {
Shinya Kitaoka 120a6e
    int skelId = ::skeletonId();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    const PlasticSkeleton::vertex_type &vx =
Shinya Kitaoka 120a6e
        m_sd->skeleton(skelId)->vertex(m_svSel);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_vertexName.setValue(vx.name().toStdWString());
Shinya Kitaoka 120a6e
    m_interpolate.setValue(vx.m_interpolate);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_minAngle.setValue((vx.m_minAngle == -l_dmax)
Shinya Kitaoka 120a6e
                            ? L""
Shinya Kitaoka 120a6e
                            : QString::number(vx.m_minAngle).toStdWString());
Shinya Kitaoka 120a6e
    m_maxAngle.setValue((vx.m_maxAngle == l_dmax)
Shinya Kitaoka 120a6e
                            ? L""
Shinya Kitaoka 120a6e
                            : QString::number(vx.m_maxAngle).toStdWString());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    vd = m_sd->vertexDeformation(skelId, m_svSel);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    m_vertexName.setValue(L"");
Shinya Kitaoka 120a6e
    m_interpolate.setValue(false);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_minAngle.setValue(L"");
Shinya Kitaoka 120a6e
    m_maxAngle.setValue(L"");
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Attach or detach relays depending on selected vertex's parameters
Shinya Kitaoka 120a6e
  m_soRelay.setParam(vd ? vd->m_params[SkVD::SO] : TDoubleParamP());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (vd && m_svSel.hasSingleObject() && m_svSel.objects().front() > 0) {
Shinya Kitaoka 120a6e
    m_distanceRelay.setParam(vd->m_params[SkVD::DISTANCE]);
Shinya Kitaoka 120a6e
    m_angleRelay.setParam(vd->m_params[SkVD::ANGLE]);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    m_distanceRelay.setParam(TDoubleParamP());
Shinya Kitaoka 120a6e
    m_angleRelay.setParam(TDoubleParamP());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_vertexName.notifyListeners();
Shinya Kitaoka 120a6e
  m_interpolate.notifyListeners();
Shinya Kitaoka 120a6e
  m_minAngle.notifyListeners();
Shinya Kitaoka 120a6e
  m_maxAngle.notifyListeners();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_distanceRelay.notifyListeners();
Shinya Kitaoka 120a6e
  m_angleRelay.notifyListeners();
Shinya Kitaoka 120a6e
  m_soRelay.notifyListeners();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::enableCommands() {
Shinya Kitaoka 120a6e
  if (TSelection::getCurrent() == &m_svSel)
Shinya Kitaoka 120a6e
    m_svSel.enableCommand(this, MI_Clear,
Shinya Kitaoka 120a6e
                          &PlasticTool::deleteSelectedVertex_undo);
Shinya Kitaoka 120a6e
  else if (TSelection::getCurrent() == &m_meSel) {
Shinya Kitaoka 120a6e
    m_meSel.enableCommand(this, MI_Clear, &PlasticTool::collapseEdge_mesh_undo);
Shinya Kitaoka 120a6e
    m_meSel.enableCommand(this, MI_Insert, &PlasticTool::splitEdge_mesh_undo);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::setSkeletonSelection(const PlasticVertexSelection &vSel) {
Shinya Kitaoka 120a6e
  if (vSel.isEmpty()) {
Shinya Kitaoka 120a6e
    m_svSel.selectNone();
Shinya Kitaoka 120a6e
    m_svSel.makeNotCurrent();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(m_sd);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_svSel.skeletonId() = m_skelId;
Shinya Kitaoka 120a6e
  m_svSel.setObjects(vSel.objects());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_svSel.notifyView();
Shinya Kitaoka 120a6e
  m_svSel.makeCurrent();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Okay, the following is cheap - we have to update the Function Editor
Shinya Kitaoka 120a6e
  // (specifically)
Shinya Kitaoka 120a6e
  // since current vertex is shown in a special color. We know that the same
Shinya Kitaoka 120a6e
  // happens for
Shinya Kitaoka 120a6e
  // the current stage object, so... we'll attach there.
Shinya Kitaoka 120a6e
  TTool::getApplication()->getCurrentObject()->notifyObjectIdChanged(
Shinya Kitaoka 120a6e
      false);  // Carry on, you've seen nothing ;)
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::toggleSkeletonSelection(
Shinya Kitaoka 120a6e
    const PlasticVertexSelection &addition) {
Shinya Kitaoka 120a6e
  const std::vector<int> &storedIdxs = m_svSel.objects();</int>
Shinya Kitaoka 120a6e
  const std::vector<int> &addedIdxs  = addition.objects();</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Build new selection
Shinya Kitaoka 120a6e
  std::vector<int> selectedIdxs;</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_svSel.contains(addition)) {
Shinya Kitaoka 120a6e
    std::set_difference(storedIdxs.begin(), storedIdxs.end(), addedIdxs.begin(),
Shinya Kitaoka 120a6e
                        addedIdxs.end(), std::back_inserter(selectedIdxs));
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    std::set_union(storedIdxs.begin(), storedIdxs.end(), addedIdxs.begin(),
Shinya Kitaoka 120a6e
                   addedIdxs.end(), std::back_inserter(selectedIdxs));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  setSkeletonSelection(selectedIdxs);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::clearSkeletonSelections() {
Shinya Kitaoka 120a6e
  m_svHigh = m_seHigh = -1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_svSel.selectNone();
Shinya Kitaoka 120a6e
  m_svSel.makeNotCurrent();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticVertexSelection PlasticTool::branchSelection(int vIdx) const {
Shinya Kitaoka 120a6e
  struct locals {
Shinya Kitaoka 120a6e
    static void addBranch(const PlasticSkeleton &skeleton, int v,
Shinya Kitaoka 120a6e
                          std::vector<int> &branch) {</int>
Shinya Kitaoka 120a6e
      branch.push_back(v);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      const PlasticSkeletonVertex &vx = skeleton.vertex(v);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      PlasticSkeletonVertex::edges_const_iterator et, eEnd = vx.edgesEnd();
Shinya Kitaoka 120a6e
      for (et = vx.edgesBegin(); et != eEnd; ++et) {
Shinya Kitaoka 120a6e
        int child = skeleton.edge(*et).vertex(1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        if (v != child)  // The edge to parent is in the list
Shinya Kitaoka 120a6e
          addBranch(skeleton, child,
Shinya Kitaoka 120a6e
                    branch);  // I wonder if it's ensured to be always at begin?
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  };
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(skeleton());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::vector<int> selectedIdxs;</int>
Shinya Kitaoka 120a6e
  locals::addBranch(*skeleton(), vIdx, selectedIdxs);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return selectedIdxs;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::copySkeleton() {
Shinya Kitaoka 120a6e
  if (!m_sd) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const PlasticSkeletonP &skel = m_sd->skeleton(::skeletonId());
Shinya Kitaoka 120a6e
  if (!skel) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Copy a CLONE of currently addressed skeleton in the app clipboard
Shinya Kitaoka 120a6e
  QMimeData *data = new PlasticSkeletonPMime(new PlasticSkeleton(*skel));
Shinya Kitaoka 120a6e
  QApplication::clipboard()->setMimeData(data, QClipboard::Clipboard);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::pasteSkeleton_undo() {
Shinya Kitaoka 120a6e
  const PlasticSkeletonPMime *data = dynamic_cast<const *="" plasticskeletonpmime="">(</const>
Shinya Kitaoka 120a6e
      QApplication::clipboard()->mimeData());
Shinya Kitaoka 120a6e
  if (!data) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  PlasticSkeletonP newSkeleton(new PlasticSkeleton(*data->m_skeleton));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  touchDeformation();
Shinya Kitaoka 120a6e
  assert(m_sd);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int skelId                      = ::skeletonId();
Shinya Kitaoka 120a6e
  const PlasticSkeletonP &oldSkel = m_sd->skeleton(skelId);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (oldSkel && !oldSkel->empty()) {
Shinya Kitaoka 120a6e
    // In case there exists a not-empty skeleton, add a NEW skeleton
Shinya Kitaoka 120a6e
    addSkeleton_undo(newSkeleton);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    TUndoManager *manager = TUndoManager::manager();
Shinya Kitaoka 120a6e
    manager->beginBlock();
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      removeSkeleton_undo(skelId);  // No problem - it's eventually empty
Shinya Kitaoka 120a6e
      addSkeleton_undo(skelId, newSkeleton.getPointer());
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    manager->endBlock();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::copyDeformation() {
Shinya Kitaoka 120a6e
  if (!m_sd) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Copy a reference to currently addressed skeleton in the app clipboard
Shinya Kitaoka 120a6e
  QMimeData *data = new SkDPMime(m_sd);
Shinya Kitaoka 120a6e
  QApplication::clipboard()->setMimeData(data, QClipboard::Clipboard);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::pasteDeformation_undo() {
Shinya Kitaoka 120a6e
  const SkDPMime *data =
Shinya Kitaoka 120a6e
      dynamic_cast<const *="" skdpmime="">(QApplication::clipboard()->mimeData());</const>
Shinya Kitaoka 120a6e
  if (!data) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Given a skeleton, attempt to assign it to the current stage object
Shinya Kitaoka 120a6e
  TStageObject *obj = ::stageObject();
Shinya Kitaoka 120a6e
  assert(obj);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const PlasticSkeletonDeformationP &oldSd =
Shinya Kitaoka 120a6e
      obj->getPlasticSkeletonDeformation();
Shinya Kitaoka 120a6e
  if (oldSd) {
Shinya Kitaoka 120a6e
    // A skeleton already exists. Ask the user if it has to be replaced.
Shinya Kitaoka 120a6e
    bool replace = DVGui::MsgBox(tr("A group of skeletons already exists for "
Shinya Kitaoka 120a6e
                                    "current column. Replacing it will also "
Shinya Kitaoka 120a6e
                                    "substitute any existing vertex "
Shinya Kitaoka 120a6e
                                    "animation.\n\nDo you want to continue?"),
Shinya Kitaoka 120a6e
                                 tr("Ok"), tr("Cancel")) == 1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (!replace) return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Clone the whole skeleton deformation (skeleton itself included)
Shinya Kitaoka 120a6e
  SkDP newSd(new PlasticSkeletonDeformation(*data->m_sd));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Insert the undo and perform the op
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(new PasteDeformationUndo(newSd));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  obj->setPlasticSkeletonDeformation(newSd);
Shinya Kitaoka 120a6e
  ::invalidateXsheet();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::setKey() {
Shinya Kitaoka 120a6e
  assert(m_svSel.hasSingleObject());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkVD *vd     = m_sd->vertexDeformation(::skeletonId(), m_svSel);
Shinya Kitaoka 120a6e
  double frame = ::frame();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (vd->isFullKeyframe(frame))
Shinya Kitaoka 120a6e
    vd->deleteKeyframe(frame);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    ::setKeyframe(vd, frame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::setGlobalKey() {
Shinya Kitaoka 120a6e
  struct locals {
Shinya Kitaoka 120a6e
    inline static bool isFullKeyframe(const SkDP &sd, double frame) {
Shinya Kitaoka 120a6e
      SkD::vd_iterator vdt, vdEnd;
Shinya Kitaoka 120a6e
      sd->vertexDeformations(vdt, vdEnd);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      for (; vdt != vdEnd; ++vdt)
Shinya Kitaoka 120a6e
        if (!(*vdt).second->isFullKeyframe(frame)) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  };
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double frame = ::frame();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (locals::isFullKeyframe(m_sd, frame))
Shinya Kitaoka 120a6e
    m_sd->deleteKeyframe(frame);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    ::setKeyframe(m_sd, frame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::setRestKey() {
Shinya Kitaoka 120a6e
  assert(m_svSel.hasSingleObject());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkVD *vd     = m_sd->vertexDeformation(::skeletonId(), m_svSel);
Shinya Kitaoka 120a6e
  double frame = ::frame();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (int p = 0; p != SkVD::PARAMS_COUNT; ++p)
Shinya Kitaoka 120a6e
    vd->m_params[p]->setValue(frame, vd->m_params[p]->getDefaultValue());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::setGlobalRestKey() {
Shinya Kitaoka 120a6e
  double frame = ::frame();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkD::vd_iterator vdt, vdEnd;
Shinya Kitaoka 120a6e
  m_sd->vertexDeformations(vdt, vdEnd);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (; vdt != vdEnd; ++vdt) {
Shinya Kitaoka 120a6e
    SkVD *vd = (*vdt).second;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    for (int p = 0; p != SkVD::PARAMS_COUNT; ++p)
Shinya Kitaoka 120a6e
      vd->m_params[p]->setValue(frame, vd->m_params[p]->getDefaultValue());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::setKey_undo() { keyFunc_undo(&PlasticTool::setKey); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::setGlobalKey_undo() {
Shinya Kitaoka 120a6e
  keyFunc_undo(&PlasticTool::setGlobalKey);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::setRestKey_undo() { keyFunc_undo(&PlasticTool::setRestKey); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::setGlobalRestKey_undo() {
Shinya Kitaoka 120a6e
  keyFunc_undo(&PlasticTool::setGlobalRestKey);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::setVertexName(QString &name) {
Shinya Kitaoka 120a6e
  const PlasticSkeletonP &skeleton = this->skeleton();
Shinya Kitaoka 120a6e
  assert(skeleton && m_svSel.hasSingleObject() && m_svSel > 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Update the selected vertex's name
Shinya Kitaoka 120a6e
  while (!m_sd->skeleton(::skeletonId())->setVertexName(m_svSel, name))
Shinya Kitaoka 120a6e
    name += "_";
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_vertexName.setValue(name.toStdWString());
Shinya Kitaoka 120a6e
  m_vertexName.notifyListeners();  // NOTE: This should NOT invoke this function
Shinya Kitaoka 120a6e
                                   // recursively
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Re-store the deformed skeleton. This is necessary since any follow-up
Shinya Kitaoka 120a6e
  // vertex
Shinya Kitaoka 120a6e
  // manipulation must refer the correct vd name.
Shinya Kitaoka 120a6e
  m_deformedSkeleton.invalidate();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  PlasticDeformerStorage::instance()->invalidateSkeleton(
Shinya Kitaoka 120a6e
      m_sd.getPointer(), ::skeletonId(), PlasticDeformerStorage::NONE);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::mouseMove(const TPointD &pos, const TMouseEvent &me) {
Shinya Kitaoka 120a6e
  // Discriminate mode
Shinya Kitaoka 120a6e
  switch (m_mode.getIndex()) {
Shinya Kitaoka 120a6e
  case MESH_IDX:
Shinya Kitaoka 120a6e
    mouseMove_mesh(pos, me);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case BUILD_IDX:
Shinya Kitaoka 120a6e
    mouseMove_build(pos, me);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case RIGIDITY_IDX:
Shinya Kitaoka 120a6e
    mouseMove_rigidity(pos, me);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case ANIMATE_IDX:
Shinya Kitaoka 120a6e
    mouseMove_animate(pos, me);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::leftButtonDown(const TPointD &pos, const TMouseEvent &me) {
Shinya Kitaoka 120a6e
  switch (m_mode.getIndex()) {
Shinya Kitaoka 120a6e
  case MESH_IDX:
Shinya Kitaoka 120a6e
    leftButtonDown_mesh(pos, me);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case BUILD_IDX:
Shinya Kitaoka 120a6e
    leftButtonDown_build(pos, me);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case RIGIDITY_IDX:
Shinya Kitaoka 120a6e
    leftButtonDown_rigidity(pos, me);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case ANIMATE_IDX:
Shinya Kitaoka 120a6e
    leftButtonDown_animate(pos, me);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
void PlasticTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &me) {
Shinya Kitaoka 120a6e
  // Track dragging status
Shinya Kitaoka 120a6e
  m_dragged = true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  switch (m_mode.getIndex()) {
Shinya Kitaoka 120a6e
  case MESH_IDX:
Shinya Kitaoka 120a6e
    leftButtonDrag_mesh(pos, me);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case BUILD_IDX:
Shinya Kitaoka 120a6e
    leftButtonDrag_build(pos, me);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case RIGIDITY_IDX:
Shinya Kitaoka 120a6e
    leftButtonDrag_rigidity(pos, me);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case ANIMATE_IDX:
Shinya Kitaoka 120a6e
    leftButtonDrag_animate(pos, me);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::leftButtonUp(const TPointD &pos, const TMouseEvent &me) {
Shinya Kitaoka 120a6e
  switch (m_mode.getIndex()) {
Shinya Kitaoka 120a6e
  case MESH_IDX:
Shinya Kitaoka 120a6e
    leftButtonUp_mesh(pos, me);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case BUILD_IDX:
Shinya Kitaoka 120a6e
    leftButtonUp_build(pos, me);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case RIGIDITY_IDX:
Shinya Kitaoka 120a6e
    leftButtonUp_rigidity(pos, me);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case ANIMATE_IDX:
Shinya Kitaoka 120a6e
    leftButtonUp_animate(pos, me);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_pressedPos = TConsts::napd;
Shinya Kitaoka 120a6e
  m_pressedVxsPos.clear();
Shinya Kitaoka 120a6e
  m_dragged = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::addContextMenuItems(QMenu *menu) {
Shinya Kitaoka 120a6e
  bool ret = true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Add global actions
Shinya Kitaoka 120a6e
  if (m_sd && m_sd->skeleton(::skeletonId())) {
Shinya Kitaoka 120a6e
    QAction *copySkeleton = menu->addAction(tr("Copy Skeleton"));
Shinya Kitaoka 120a6e
    ret = ret && connect(copySkeleton, SIGNAL(triggered()), &l_plasticTool,
Shinya Kitaoka 120a6e
                         SLOT(copySkeleton()));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (dynamic_cast<const *="" plasticskeletonpmime="">(</const>
Shinya Kitaoka 120a6e
          QApplication::clipboard()->mimeData())) {
Shinya Kitaoka 120a6e
    QAction *pasteSkeleton = menu->addAction(tr("Paste Skeleton"));
Shinya Kitaoka 120a6e
    ret = ret && connect(pasteSkeleton, SIGNAL(triggered()), &l_plasticTool,
Shinya Kitaoka 120a6e
                         SLOT(pasteSkeleton_undo()));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  menu->addSeparator();  // Separate actions type
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Add editing actions
Shinya Kitaoka 120a6e
  switch (m_mode.getIndex()) {
Shinya Kitaoka 120a6e
  case MESH_IDX:
Shinya Kitaoka 120a6e
    addContextMenuActions_mesh(menu);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case BUILD_IDX:
Shinya Kitaoka 120a6e
    addContextMenuActions_build(menu);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case RIGIDITY_IDX:
Shinya Kitaoka 120a6e
    addContextMenuActions_rigidity(menu);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case ANIMATE_IDX:
Shinya Kitaoka 120a6e
    addContextMenuActions_animate(menu);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Add view actions
Shinya Kitaoka 120a6e
  QAction *showMesh = menu->addAction(tr("Show Mesh"));
Shinya Kitaoka 120a6e
  showMesh->setCheckable(true);
Shinya Kitaoka 120a6e
  showMesh->setChecked(m_pvs.m_drawMeshesWireframe);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ret = ret && connect(showMesh, SIGNAL(triggered(bool)), &l_plasticTool,
Shinya Kitaoka 120a6e
                       SLOT(onShowMeshToggled(bool)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  QAction *showRigidity = menu->addAction(tr("Show Rigidity"));
Shinya Kitaoka 120a6e
  showRigidity->setCheckable(true);
Shinya Kitaoka 120a6e
  showRigidity->setChecked(m_pvs.m_drawRigidity);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ret = ret && connect(showRigidity, SIGNAL(triggered(bool)), &l_plasticTool,
Shinya Kitaoka 120a6e
                       SLOT(onShowRigidityToggled(bool)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  QAction *showSO = menu->addAction(tr("Show SO"));
Shinya Kitaoka 120a6e
  showSO->setCheckable(true);
Shinya Kitaoka 120a6e
  showSO->setChecked(m_pvs.m_drawSO);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ret = ret && connect(showSO, SIGNAL(triggered(bool)), &l_plasticTool,
Shinya Kitaoka 120a6e
                       SLOT(onShowSOToggled(bool)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  QAction *showSkeletonOS = menu->addAction(tr("Show Skeleton Onion Skin"));
Shinya Kitaoka 120a6e
  showSkeletonOS->setCheckable(true);
Shinya Kitaoka 120a6e
  showSkeletonOS->setChecked(m_showSkeletonOS);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ret = ret && connect(showSkeletonOS, SIGNAL(triggered(bool)), &l_plasticTool,
Shinya Kitaoka 120a6e
                       SLOT(onShowSkelOSToggled(bool)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(ret);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  menu->addSeparator();  // Separate from common view options
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
void PlasticTool::reset() {
Shinya Kitaoka 120a6e
  // NOTE: This is an inherited virtual. Please leave it even if it's empty.
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
bool PlasticTool::onPropertyChanged(std::string propertyName) {
Shinya Kitaoka 120a6e
  struct locals {
Shinya Kitaoka 120a6e
    static bool alreadyContainsVertexName(const PlasticSkeleton &skel,
Shinya Kitaoka 120a6e
                                          const QString &name) {
Shinya Kitaoka 120a6e
      tcg::list<plasticskeletonvertex>::const_iterator vt,</plasticskeletonvertex>
Shinya Kitaoka 120a6e
          vEnd(skel.vertices().end());
Shinya Kitaoka 120a6e
      for (vt = skel.vertices().begin(); vt != vEnd; ++vt)
Shinya Kitaoka 120a6e
        if (vt->name() == name) return true;
Shinya Kitaoka 120a6e
      return false;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    static int vdCount(const SkDP &sd, const QString &name) {
Shinya Kitaoka 120a6e
      SkD::vx_iterator vxBegin, vxEnd;
Shinya Kitaoka 120a6e
      sd->vdSkeletonVertices(name, vxBegin, vxEnd);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      return std::distance(vxBegin, vxEnd);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  };  // locals
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (propertyName == "mode") {
Shinya Kitaoka 120a6e
    switch (m_mode.getIndex()) {
Shinya Kitaoka 120a6e
    case MESH_IDX:
Shinya Kitaoka 120a6e
    case BUILD_IDX:
Shinya Kitaoka 120a6e
    case RIGIDITY_IDX:
Shinya Kitaoka 120a6e
      m_pvs.m_showOriginalColumn = xshColumn();
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    case ANIMATE_IDX:
Shinya Kitaoka 120a6e
      m_pvs.m_showOriginalColumn = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (m_svSel.objects().size() > 1) setSkeletonSelection(-1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      storeDeformation();  // Rebuild deformed skeleton
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_mode.notifyListeners();  // You thought that was automatic, eh? BTW, this
Shinya Kitaoka 120a6e
                               // means
Shinya Kitaoka 120a6e
    // we're requesting toolbars to update options visibility
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    onSetViewer();  // Store m_pvs in the viewer's visual settings
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
  } else if (propertyName == "vertexName") {
Shinya Kitaoka 120a6e
    if (m_sd && m_svSel >= 0) {
Shinya Kitaoka 120a6e
      // Update the selected vertex's name
Shinya Kitaoka 120a6e
      QString newName(QString::fromStdWString(m_vertexName.getValue()));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      const PlasticSkeletonP skeleton = this->skeleton();
Shinya Kitaoka 120a6e
      assert(skeleton);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      const QString &oldName = skeleton->vertex(m_svSel).name();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      bool doRename = true;
Shinya Kitaoka 120a6e
      if (oldName != newName &&
Shinya Kitaoka 120a6e
          !locals::alreadyContainsVertexName(*skeleton, newName) &&
Shinya Kitaoka 120a6e
          m_sd->vertexDeformation(newName) &&
Shinya Kitaoka 120a6e
          locals::vdCount(m_sd, oldName) == 1)
Shinya Kitaoka 120a6e
        doRename =
Shinya Kitaoka 120a6e
            (DVGui::MsgBox(
Shinya Kitaoka 120a6e
                 tr("The previous vertex name will be discarded, and all "
Shinya Kitaoka 120a6e
                    "associated keys will be lost.\n\nDo you want to proceed?"),
Shinya Kitaoka 120a6e
                 QObject::tr("Ok"), QObject::tr("Cancel")) == 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      if (doRename) {
Shinya Kitaoka 120a6e
        TUndo *undo = new SetVertexNameUndo(m_svSel, newName);
Shinya Kitaoka 120a6e
        TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        undo->redo();
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        m_vertexName.setValue(oldName.toStdWString());
Shinya Kitaoka 120a6e
        m_vertexName.notifyListeners();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else if (propertyName == "interpolate") {
Shinya Kitaoka 120a6e
    if (m_sd && m_svSel >= 0) {
Shinya Kitaoka 120a6e
      // Set interpolation property to the associated skeleton vertex
Shinya Kitaoka 120a6e
      int skelId = ::skeletonId();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_sd->skeleton(skelId)->vertex(m_svSel).m_interpolate =
Shinya Kitaoka 120a6e
          m_interpolate.getValue();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_interpolate.notifyListeners();  // NOTE: This should NOT invoke this
Shinya Kitaoka 120a6e
                                        // function recursively
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      PlasticDeformerStorage::instance()->invalidateSkeleton(
Shinya Kitaoka 120a6e
          m_sd.getPointer(), skelId, PlasticDeformerStorage::ALL);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else if (propertyName == "minAngle") {
Shinya Kitaoka 120a6e
    if (m_sd && m_svSel >= 0) {
Shinya Kitaoka 120a6e
      // Set maxAngle property to the associated skeleton vertex
Shinya Kitaoka 120a6e
      int skelId = ::skeletonId();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      bool ok;
Shinya Kitaoka 120a6e
      double value =
Shinya Kitaoka 120a6e
          QString::fromStdWString(m_minAngle.getValue()).toDouble(&ok);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      if (!ok) value = -l_dmax, m_minAngle.setValue(L"");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_sd->skeleton(skelId)->vertex(m_svSel).m_minAngle = value;
Shinya Kitaoka 120a6e
      if (m_mode.getIndex() == ANIMATE_IDX)
Shinya Kitaoka 120a6e
        deformedSkeleton().vertex(m_svSel).m_minAngle = value;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_minAngle.notifyListeners();  // NOTE: This should NOT invoke this
Shinya Kitaoka 120a6e
                                     // function recursively
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else if (propertyName == "maxAngle") {
Shinya Kitaoka 120a6e
    if (m_sd && m_svSel >= 0) {
Shinya Kitaoka 120a6e
      // Set maxAngle property to the associated skeleton vertex
Shinya Kitaoka 120a6e
      int skelId = ::skeletonId();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      bool ok;
Shinya Kitaoka 120a6e
      double value =
Shinya Kitaoka 120a6e
          QString::fromStdWString(m_maxAngle.getValue()).toDouble(&ok);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      if (!ok) value = l_dmax, m_maxAngle.setValue(L"");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_sd->skeleton(skelId)->vertex(m_svSel).m_maxAngle = value;
Shinya Kitaoka 120a6e
      if (m_mode.getIndex() == ANIMATE_IDX)
Shinya Kitaoka 120a6e
        deformedSkeleton().vertex(m_svSel).m_maxAngle = value;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_maxAngle.notifyListeners();  // NOTE: This should NOT invoke this
Shinya Kitaoka 120a6e
                                     // function recursively
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::onShowMeshToggled(bool on) {
Shinya Kitaoka 120a6e
  m_pvs.m_drawMeshesWireframe = on;
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::onShowSOToggled(bool on) {
Shinya Kitaoka 120a6e
  m_pvs.m_drawSO = on;
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::onShowRigidityToggled(bool on) {
Shinya Kitaoka 120a6e
  m_pvs.m_drawRigidity = on;
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::onShowSkelOSToggled(bool on) {
Shinya Kitaoka 120a6e
  m_showSkeletonOS = on;
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    Drawing functions
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace PlasticToolLocals {
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void drawSquare(const TPointD &pos, double radius) {
Shinya Kitaoka 120a6e
  glBegin(GL_LINE_LOOP);
Shinya Kitaoka 120a6e
  glVertex2d(pos.x - radius, pos.y - radius);
Shinya Kitaoka 120a6e
  glVertex2d(pos.x + radius, pos.y - radius);
Shinya Kitaoka 120a6e
  glVertex2d(pos.x + radius, pos.y + radius);
Shinya Kitaoka 120a6e
  glVertex2d(pos.x - radius, pos.y + radius);
Shinya Kitaoka 120a6e
  glEnd();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void drawFullSquare(const TPointD &pos, double radius) {
Shinya Kitaoka 120a6e
  glBegin(GL_QUADS);
Shinya Kitaoka 120a6e
  glVertex2d(pos.x - radius, pos.y - radius);
Shinya Kitaoka 120a6e
  glVertex2d(pos.x + radius, pos.y - radius);
Shinya Kitaoka 120a6e
  glVertex2d(pos.x + radius, pos.y + radius);
Shinya Kitaoka 120a6e
  glVertex2d(pos.x - radius, pos.y + radius);
Shinya Kitaoka 120a6e
  glEnd();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Campbell Barton 8c6c57
static void drawFilledSquare(const TPointD &pos, double radius) {
Shinya Kitaoka 120a6e
  glBegin(GL_QUADS);
Shinya Kitaoka 120a6e
  glVertex2d(pos.x - radius, pos.y - radius);
Shinya Kitaoka 120a6e
  glVertex2d(pos.x + radius, pos.y - radius);
Shinya Kitaoka 120a6e
  glVertex2d(pos.x + radius, pos.y + radius);
Shinya Kitaoka 120a6e
  glVertex2d(pos.x - radius, pos.y + radius);
Shinya Kitaoka 120a6e
  glEnd();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
shun-iwasawa 27b0cf
static void drawHandle(const TPointD &pos, double radius,
shun-iwasawa 27b0cf
                       const TPixel32 &color) {
Shinya Kitaoka 120a6e
  glColor4ub(0, 0, 0, color.m);  // Black border
Shinya Kitaoka 120a6e
  glLineWidth(4.0f);
Shinya Kitaoka 120a6e
  drawSquare(pos, radius);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glColor4ub(color.r, color.g, color.b, color.m);
Shinya Kitaoka 120a6e
  glLineWidth(2.0f);
Shinya Kitaoka 120a6e
  drawSquare(pos, radius);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
shun-iwasawa 27b0cf
static void drawFilledHandle(const TPointD &pos, double radius,
shun-iwasawa 27b0cf
                             double pixelSize, const TPixel32 &color) {
Shinya Kitaoka 120a6e
  glColor4ub(0, 0, 0, color.m);
Shinya Kitaoka 120a6e
  drawFilledSquare(pos, radius + pixelSize);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glColor4ub(color.r, color.g, color.b, color.m);
Shinya Kitaoka 120a6e
  drawFilledSquare(pos, radius);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
shun-iwasawa 27b0cf
static void drawText(const TPointD &pos, const QString &text,
shun-iwasawa 27b0cf
                     double fontScale) {
Shinya Kitaoka 120a6e
  // Get the world-to-window affine
Shinya Kitaoka 120a6e
  double matrix[16];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glGetDoublev(GL_MODELVIEW_MATRIX, matrix);
Shinya Kitaoka 120a6e
  TAffine worldToWindowAff(matrix[0], matrix[4], matrix[12], matrix[1],
Shinya Kitaoka 120a6e
                           matrix[5], matrix[13]);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Push the window reference
Shinya Kitaoka 120a6e
  glPushMatrix();
Shinya Kitaoka 120a6e
  glLoadIdentity();
Shinya Kitaoka 120a6e
  glScaled(fontScale, fontScale, 1.0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  tglDrawText(TScale(1.0 / fontScale) * worldToWindowAff * pos,
Shinya Kitaoka 120a6e
              text.toStdWString());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Bottom-left fixed text version
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // double origin = 10.0 / fontScale
Shinya Kitaoka 120a6e
  // tglDrawText(TPointD(origin, origin), text.toStdWString());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glPopMatrix();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace PlasticToolLocals
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//========================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::drawHighlights(const SkDP &sd,
Shinya Kitaoka 120a6e
                                 const PlasticSkeleton *skeleton,
Shinya Kitaoka 120a6e
                                 double pixelSize) {
Shinya Kitaoka 120a6e
  glColor3f(1.0f, 0.0f, 0.0f);  // Red
Shinya Kitaoka 120a6e
  glLineWidth(1.0f);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Vertex highlights
Shinya Kitaoka 120a6e
  if (m_svHigh >= 0) {
Shinya Kitaoka 120a6e
    double handleRadius = HIGHLIGHTED_HANDLE_SIZE * pixelSize;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    const PlasticSkeleton::vertex_type &vx = skeleton->vertex(m_svHigh);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    int hookNumber = sd->hookNumber(vx.name());
Shinya Kitaoka 120a6e
    assert(hookNumber >= 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      glPushAttrib(GL_LINE_BIT);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      glEnable(GL_LINE_STIPPLE);
Shinya Kitaoka 120a6e
      glLineStipple(1, 0xCCCC);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      drawSquare(vx.P(), handleRadius);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      glPopAttrib();
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    drawText(vx.P() + TPointD(2.0 * handleRadius, 2.0 * handleRadius),
Shinya Kitaoka 120a6e
             QString("(%1) ").arg(hookNumber) + vx.name(), 1.7);
Shinya Kitaoka 120a6e
  } else if (m_seHigh >= 0) {
Shinya Kitaoka 120a6e
    // Draw a handle at the projection of current mouse position towards the
Shinya Kitaoka 120a6e
    // highlighted edge
Shinya Kitaoka 120a6e
    double handleRadius = HANDLE_SIZE * pixelSize;
Shinya Kitaoka 120a6e
    drawSquare(projection(*skeleton, m_seHigh, m_pos), handleRadius);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::drawSelections(const SkDP &sd,
Shinya Kitaoka 120a6e
                                 const PlasticSkeleton &skeleton,
Shinya Kitaoka 120a6e
                                 double pixelSize) {
Shinya Kitaoka 120a6e
  glColor3f(1.0f, 0.0f, 0.0f);  // Red
Shinya Kitaoka 120a6e
  glLineWidth(1.0f);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double handleRadius = SELECTED_HANDLE_SIZE * pixelSize;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_svSel.isEmpty()) {
Shinya Kitaoka 120a6e
    typedef PlasticVertexSelection::objects_container objects_container;
Shinya Kitaoka 120a6e
    const objects_container &vIdxs = m_svSel.objects();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Draw a handle square for each selected vertex
Shinya Kitaoka 120a6e
    objects_container::const_iterator vst, vsEnd = vIdxs.end();
Shinya Kitaoka 120a6e
    for (vst = vIdxs.begin(); vst != vsEnd; ++vst)
Shinya Kitaoka 120a6e
      drawSquare(skeleton.vertex(*vst).P(), handleRadius);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Draw vertex descriptions (only in the single selection case - to avoid
Shinya Kitaoka 120a6e
    // text pollution)
Shinya Kitaoka 120a6e
    if (vIdxs.size() == 1) {
Shinya Kitaoka 120a6e
      const PlasticSkeleton::vertex_type &vx = skeleton.vertex(m_svSel);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      int hookNumber = sd->hookNumber(vx.name());
Shinya Kitaoka 120a6e
      assert(hookNumber >= 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      drawText(vx.P() + TPointD(2.0 * handleRadius, 2.0 * handleRadius),
Shinya Kitaoka 120a6e
               QString("(%1) ").arg(hookNumber) + vx.name(), 1.7);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::drawSkeleton(const PlasticSkeleton &skel, double pixelSize,
Shinya Kitaoka 120a6e
                               UCHAR alpha) {
Shinya Kitaoka 120a6e
  struct locals {
Shinya Kitaoka 120a6e
    inline static void drawLine(const TPointD &p0, const TPointD &p1) {
Shinya Kitaoka 120a6e
      glVertex2d(p0.x, p0.y);
Shinya Kitaoka 120a6e
      glVertex2d(p1.x, p1.y);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  };  // locals
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const tcg::list<plasticskeleton::vertex_type> &vertices = skel.vertices();</plasticskeleton::vertex_type>
Shinya Kitaoka 120a6e
  if (vertices.size() > 0) {
Shinya Kitaoka 120a6e
    // Draw edges
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      const tcg::list<plasticskeleton::edge_type> &edges = skel.edges();</plasticskeleton::edge_type>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      tcg::list<plasticskeleton::edge_type>::const_iterator et,</plasticskeleton::edge_type>
Shinya Kitaoka 120a6e
          eEnd(edges.end());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      glColor4ub(0, 0, 0, alpha);
Shinya Kitaoka 120a6e
      glLineWidth(4.0f);  // Black border
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      glBegin(GL_LINES);
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        for (et = edges.begin(); et != eEnd; ++et)
Shinya Kitaoka 120a6e
          locals::drawLine(skel.vertex(et->vertex(0)).P(),
Shinya Kitaoka 120a6e
                           skel.vertex(et->vertex(1)).P());
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      glEnd();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      glColor4ub(250, 184, 70, alpha);
Shinya Kitaoka 120a6e
      glLineWidth(2.0f);  // Yellow/Orange-ish line center
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      glBegin(GL_LINES);
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        for (et = edges.begin(); et != eEnd; ++et)
Shinya Kitaoka 120a6e
          locals::drawLine(skel.vertex(et->vertex(0)).P(),
Shinya Kitaoka 120a6e
                           skel.vertex(et->vertex(1)).P());
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      glEnd();
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Draw vertices
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      const TPixel32 magenta(255, 0, 255, alpha);
Shinya Kitaoka 120a6e
      const TPixel32 yellow(255, 255, 0, alpha);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      double handleRadius  = HANDLE_SIZE * pixelSize;
Shinya Kitaoka 120a6e
      float intHandleThick = 2.0f, extHandleThick = 4.0f;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      // Draw root
Shinya Kitaoka 120a6e
      drawFilledHandle(vertices.begin()->P(), handleRadius, pixelSize, magenta);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      // Draw remaining vertices
Shinya Kitaoka 120a6e
      tcg::list<plasticskeleton::vertex_type>::const_iterator vt(</plasticskeleton::vertex_type>
Shinya Kitaoka 120a6e
          vertices.begin()),
Shinya Kitaoka 120a6e
          vEnd(vertices.end());
Shinya Kitaoka 120a6e
      if (vt != vEnd) {
Shinya Kitaoka 120a6e
        for (vt = ++vertices.begin(); vt != vEnd; ++vt)
Shinya Kitaoka 120a6e
          drawHandle(vt->P(), handleRadius,
Shinya Kitaoka 120a6e
                     vt->m_interpolate ? magenta : yellow);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::drawOnionSkinSkeletons_build(double pixelSize) {
Shinya Kitaoka 120a6e
  if (!(m_showSkeletonOS && m_sd)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const OnionSkinMask &os =
Shinya Kitaoka 120a6e
      TTool::getApplication()->getCurrentOnionSkin()->getOnionSkinMask();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<int> osRows;</int>
Shinya Kitaoka 120a6e
  int currentRow = ::row();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  os.getAll(currentRow, osRows);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TStageObject *obj = ::stageObject();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Sieve osRows' associated skeleton ids first
Shinya Kitaoka 120a6e
  std::map<int, uchar=""> skelAlphas;</int,>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int r, rCount = int(osRows.size());
Shinya Kitaoka 120a6e
  for (r = 0; r != rCount; ++r) {
Shinya Kitaoka 120a6e
    assert(osRows[r] != currentRow);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    double sdFrame = obj->paramsTime(double(osRows[r] - 1));
Shinya Kitaoka 120a6e
    int skelId     = m_sd->skeletonId(sdFrame);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    UCHAR &skelAlpha = skelAlphas[skelId];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    UCHAR alpha =
Shinya Kitaoka 120a6e
        255 -
Shinya Kitaoka 120a6e
        UCHAR(255.0 * OnionSkinMask::getOnionSkinFade(osRows[r] - currentRow));
Shinya Kitaoka 120a6e
    skelAlpha = std::max(skelAlpha, alpha);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::map<int, uchar="">::iterator st, sEnd(skelAlphas.end());</int,>
Shinya Kitaoka 120a6e
  for (st = skelAlphas.begin(); st != sEnd; ++st) {
Shinya Kitaoka 120a6e
    const PlasticSkeletonP &skel = m_sd->skeleton(st->first);
Shinya Kitaoka 120a6e
    drawSkeleton(*skel, pixelSize, st->second);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::drawOnionSkinSkeletons_animate(double pixelSize) {
Shinya Kitaoka 120a6e
  if (!(m_showSkeletonOS && m_sd)) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const OnionSkinMask &os =
Shinya Kitaoka 120a6e
      TTool::getApplication()->getCurrentOnionSkin()->getOnionSkinMask();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::vector<int> osRows;</int>
Shinya Kitaoka 120a6e
  int currentRow = ::row();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  os.getAll(currentRow, osRows);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TStageObject *obj = ::stageObject();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int r, rCount = int(osRows.size());
Shinya Kitaoka 120a6e
  for (r = 0; r != rCount; ++r) {
Shinya Kitaoka 120a6e
    assert(osRows[r] != currentRow);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    double sdFrame = obj->paramsTime(double(osRows[r] - 1));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    PlasticSkeleton skel;
Shinya Kitaoka 120a6e
    m_sd->storeDeformedSkeleton(m_sd->skeletonId(sdFrame), sdFrame, skel);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    UCHAR alpha =
Shinya Kitaoka 120a6e
        255 -
Shinya Kitaoka 120a6e
        255.0 * OnionSkinMask::getOnionSkinFade(abs(osRows[r] - currentRow));
Shinya Kitaoka 120a6e
    drawSkeleton(skel, pixelSize, alpha);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticTool::drawAngleLimits(const SkDP &sd, int skelId, int v,
Shinya Kitaoka 120a6e
                                  double pixelSize) {
Shinya Kitaoka 120a6e
  struct {
Shinya Kitaoka 120a6e
    PlasticTool *m_this;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    void drawAnnulusArc(const TPointD ¢er, double angleStart,
Shinya Kitaoka 120a6e
                        double angleEnd, double radiusA, double radiusB,
Shinya Kitaoka 120a6e
                        double pixelSize) {
Shinya Kitaoka 120a6e
      double angleDelta = acos(1.0 - pixelSize / std::max(radiusA, radiusB)) *
Shinya Kitaoka 120a6e
                          ((angleStart <= angleEnd) ? 1.0 : -1.0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      int a, aCount = tcg::numeric_ops::grow(
Shinya Kitaoka 120a6e
                 fabs((angleEnd - angleStart) / angleDelta));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      glBegin(GL_QUAD_STRIP);
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        for (a = 0; a != aCount; ++a) {
Shinya Kitaoka 120a6e
          double angle = angleStart + a * angleDelta;
Shinya Kitaoka 120a6e
          TPointD direction(cos(angle), sin(angle));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
          tglVertex(center + radiusA * direction);
Shinya Kitaoka 120a6e
          tglVertex(center + radiusB * direction);
Shinya Kitaoka 120a6e
        }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        TPointD direction(cos(angleEnd), sin(angleEnd));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        tglVertex(center + radiusA * direction);
Shinya Kitaoka 120a6e
        tglVertex(center + radiusB * direction);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      glEnd();
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    void drawLimit(const SkDP &sd, int skelId, int v, double angleLimit,
Shinya Kitaoka 120a6e
                   double pixelSize) {
Shinya Kitaoka 120a6e
      const PlasticSkeleton &skel    = *sd->skeleton(skelId);
Shinya Kitaoka 120a6e
      const PlasticSkeleton &defSkel = m_this->deformedSkeleton();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      const PlasticSkeletonVertex &vx    = skel.vertex(v);
Shinya Kitaoka 120a6e
      const PlasticSkeletonVertex &defVx = defSkel.vertex(v);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      int vParent = vx.parent();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      const PlasticSkeletonVertex &vxParent    = skel.vertex(vParent);
Shinya Kitaoka 120a6e
      const PlasticSkeletonVertex &defVxParent = defSkel.vertex(vParent);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      // Build directions
Shinya Kitaoka 120a6e
      int vGrandParent = vxParent.parent();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      TPointD dirFromParent(vx.P() - vxParent.P()), dirFromGrandParent(1, 0),
Shinya Kitaoka 120a6e
          dirFromDeformedGrandParent(1, 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      if (vGrandParent >= 0) {
Shinya Kitaoka 120a6e
        const PlasticSkeletonVertex &vxGrandParent = skel.vertex(vGrandParent),
Shinya Kitaoka 120a6e
                                    &defVxGrandParent =
Shinya Kitaoka 120a6e
                                        defSkel.vertex(vGrandParent);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        dirFromGrandParent         = vxParent.P() - vxGrandParent.P();
Shinya Kitaoka 120a6e
        dirFromDeformedGrandParent = defVxParent.P() - defVxGrandParent.P();
Shinya Kitaoka 120a6e
      }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      // Retrieve angular data
Shinya Kitaoka 120a6e
      double angleShift =
Shinya Kitaoka 120a6e
          sd->vertexDeformation(skelId, v)->m_params[SkVD::ANGLE]->getValue(
Shinya Kitaoka 120a6e
              ::frame());
Shinya Kitaoka 120a6e
      double defaultAngleValue =
Shinya Kitaoka 120a6e
          tcg::point_ops::angle(dirFromGrandParent, dirFromParent) * M_180_PI;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      // Convert to radians
Shinya Kitaoka 120a6e
      double currentBranchAngle_rad =
Shinya Kitaoka 120a6e
          tcg::point_ops::rad(dirFromDeformedGrandParent);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      double currentAngle_rad =
Shinya Kitaoka 120a6e
          currentBranchAngle_rad + (angleShift + defaultAngleValue) * M_PI_180;
Shinya Kitaoka 120a6e
      double limitDirection_rad =
Shinya Kitaoka 120a6e
          currentBranchAngle_rad + (angleLimit + defaultAngleValue) * M_PI_180;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      glColor4ub(0, 0, 255, 128);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      // Draw limit lines
Shinya Kitaoka 120a6e
      if (angleShift - 180.0 <= angleLimit &&
Shinya Kitaoka 120a6e
          angleLimit <= angleShift + 180.0) {
Shinya Kitaoka 120a6e
        TPointD limitDirection(cos(limitDirection_rad),
Shinya Kitaoka 120a6e
                               sin(limitDirection_rad));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        glBegin(GL_LINES);
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
          tglVertex(defVxParent.P());
Shinya Kitaoka 120a6e
          tglVertex(defVxParent.P() + 1e4 * limitDirection);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        glEnd();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Draw limit annulus arc
Shinya Kitaoka 120a6e
      angleLimit = tcrop(angleLimit, angleShift - 180.0, angleShift + 180.0);
Shinya Kitaoka 120a6e
      limitDirection_rad =
Shinya Kitaoka 120a6e
          currentBranchAngle_rad + (angleLimit + defaultAngleValue) * M_PI_180;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      double radius = tcg::point_ops::dist(defVx.P(), defVxParent.P()) * 0.25;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      drawAnnulusArc(defVxParent.P(), limitDirection_rad, currentAngle_rad,
Shinya Kitaoka 120a6e
                     radius - 5.0 * pixelSize, radius + 5.0 * pixelSize,
Shinya Kitaoka 120a6e
                     pixelSize);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } locals = {this};
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Dismiss no-ops
Shinya Kitaoka 120a6e
  const PlasticSkeletonP &skel = sd->skeleton(skelId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!skel || v < 0) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Ensure we're editing a vertex with an existing parent
Shinya Kitaoka 120a6e
  if (m_dragged) {
Shinya Kitaoka 120a6e
    const PlasticSkeletonVertex &vx = skel->vertex(v);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int vParent = vx.parent();
Shinya Kitaoka 120a6e
    if (vParent >= 0) {
Shinya Kitaoka 120a6e
      // Draw angular limits
Shinya Kitaoka 120a6e
      if (vx.m_minAngle != -l_dmax)
Shinya Kitaoka 120a6e
        locals.drawLimit(sd, skelId, v, vx.m_minAngle, pixelSize);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (vx.m_maxAngle != l_dmax)
Shinya Kitaoka 120a6e
        locals.drawLimit(sd, skelId, v, vx.m_maxAngle, pixelSize);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
void PlasticTool::draw() {
Shinya Kitaoka 120a6e
  glPushAttrib(GL_LINE_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glEnable(GL_BLEND);
Shinya Kitaoka 120a6e
  glEnable(GL_LINE_SMOOTH);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  switch (m_mode.getIndex()) {
Shinya Kitaoka 120a6e
  case MESH_IDX:
Shinya Kitaoka 120a6e
    draw_mesh();
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case BUILD_IDX:
Shinya Kitaoka 120a6e
    draw_build();
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case RIGIDITY_IDX:
Shinya Kitaoka 120a6e
    draw_rigidity();
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case ANIMATE_IDX:
Shinya Kitaoka 120a6e
    draw_animate();
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  };
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glPopAttrib();
Toshihiro Shimizu 890ddd
}