249386
249386
// TnzTools includes
249386
#include <tools tool.h=""></tools>
249386
#include <tools toolutils.h=""></tools>
249386
#include <tools toolhandle.h=""></tools>
249386
#include <tools cursors.h=""></tools>
249386
#include <tools assistant.h=""></tools>
249386
249386
// TnzLib includes
249386
#include <toonz tapplication.h=""></toonz>
249386
#include <toonz txshlevelhandle.h=""></toonz>
249386
249386
// TnzCore includes
249386
#include <tgl.h></tgl.h>
249386
#include <tproperty.h></tproperty.h>
249386
#include <tmetaimage.h></tmetaimage.h>
249386
249386
// For Qt translation support
249386
#include <qcoreapplication></qcoreapplication>
249386
249386
#include <map></map>
249386
249386
249386
//-------------------------------------------------------------------
249386
249386
//=============================================================================
249386
// Edit Assistants Undo
249386
//-----------------------------------------------------------------------------
249386
249386
class EditAssistantsUndo final : public ToolUtils::TToolUndo {
249386
private:
249386
  bool m_isAssistantCreated;
249386
  TMetaObjectP m_metaObject;
249386
  TVariant m_oldData;
249386
  TVariant m_newData;
249386
  size_t m_size;
249386
249386
public:
249386
  EditAssistantsUndo(
249386
    TXshSimpleLevel *level,
249386
    const TFrameId &frameId,
249386
    bool isAssistantCreated,
249386
    TMetaObjectR metaObject,
249386
    TVariant oldData
249386
  ):
249386
    ToolUtils::TToolUndo(level, frameId),
249386
    m_isAssistantCreated(isAssistantCreated),
249386
    m_metaObject(metaObject.getPointer()),
249386
    m_oldData(oldData),
249386
    m_newData(m_metaObject->data()),
249386
    m_size(m_oldData.getMemSize() + m_newData.getMemSize())
249386
  { }
249386
249386
  int getSize() const override
249386
    { return m_size; }
249386
  QString getToolName() override
249386
    { return QString("Edit Assistants Tool"); }
249386
249386
  void undo() const override {
249386
    if (TMetaImage *metaImage = dynamic_cast<tmetaimage*>(m_level->getFrame(m_frameId, true).getPointer())) {</tmetaimage*>
249386
      TMetaImage::Writer writer(*metaImage);
249386
      if (m_isAssistantCreated) {
249386
        for(TMetaObjectRefList::iterator i = writer->begin(); i != writer->end(); ++i)
249386
          if (*i == m_metaObject) { writer->erase(i); break; }
249386
      } else {
249386
        m_metaObject->data() = m_oldData;
249386
        if (TMetaObjectHandler *handler = m_metaObject->getHandler<tmetaobjecthandler>())</tmetaobjecthandler>
249386
          handler->fixData();
249386
      }
249386
      notifyImageChanged();
249386
    }
249386
  }
249386
249386
  void redo() const override {
249386
    if (TMetaImage *metaImage = dynamic_cast<tmetaimage*>(m_level->getFrame(m_frameId, true).getPointer())) {</tmetaimage*>
249386
      TMetaImage::Writer writer(*metaImage);
249386
      m_metaObject->data() = m_newData;
249386
      if (TMetaObjectHandler *handler = m_metaObject->getHandler<tmetaobjecthandler>())</tmetaobjecthandler>
249386
        handler->fixData();
249386
      if (m_isAssistantCreated)
249386
        writer->push_back(TMetaObjectR(m_metaObject.getPointer()));
249386
      notifyImageChanged();
249386
    }
249386
  }
249386
};
249386
249386
249386
//=============================================================================
249386
// Edit Assistants Tool
249386
//-----------------------------------------------------------------------------
249386
249386
class EditAssistantsTool final : public TTool {
249386
  Q_DECLARE_TR_FUNCTIONS(EditAssistantsTool)
249386
public:
249386
  typedef std::map<std::wstring, tstringid=""> TypeMap;</std::wstring,>
249386
249386
protected:
249386
  TPropertyGroup m_prop;
249386
  TEnumProperty m_assistantType;
249386
  TypeMap m_localnameToType;
249386
  TStringId m_newAssisnantType;
249386
249386
  bool           m_dragging;
249386
  bool           m_currentAssistantCreated;
249386
  int            m_currentAssistantIndex;
249386
  int            m_currentPointIndex;
249386
  TPointD        m_currentPointOffset;
249386
  TVariant       m_currentAssistantBackup;
249386
  TPointD        m_currentPosition;
249386
  TGuidelineList m_currentGuidelines;
249386
249386
public:
249386
  EditAssistantsTool():
249386
    TTool("T_EditAssistants"),
249386
    m_assistantType("AssistantType"),
249386
    m_dragging(),
249386
    m_currentAssistantCreated(),
249386
    m_currentAssistantIndex(-1),
249386
    m_currentPointIndex(-1)
249386
  {
249386
    bind(MetaImage);
249386
    m_prop.add(&m_assistantType);
249386
    updateTranslation();
249386
  }
249386
  
249386
  ~EditAssistantsTool()
249386
    { m_prop.clear(); }
249386
249386
  ToolType getToolType() const override
249386
    { return TTool::LevelWriteTool; }
249386
  int getCursorId() const override
249386
    { return ToolCursor::StrokeSelectCursor; }
249386
  TPropertyGroup* getProperties(int targetType) override
249386
    { return &m_prop; }
249386
  void onImageChanged() override
249386
    { getViewer()->GLInvalidateAll(); }
249386
249386
  void addAssistantType(const std::string &name, const std::string &typeName) {
249386
    const std::wstring localName = tr(name.c_str()).toStdWString();
249386
    if (m_localnameToType.count(localName)) return;
249386
    m_localnameToType[localName] = TStringId(typeName);
249386
    m_assistantType.addValue(localName);
249386
  }
249386
249386
  void updateTranslation() override {
249386
    m_assistantType.setQStringName(tr("Assistant Type"));
249386
    m_assistantType.deleteAllValues();
249386
    m_localnameToType.clear();
249386
    addAssistantType("--", "");
249386
    addAssistantType("Vanishing Point", "assistantVanishingPoint");
249386
    m_assistantType.setIndex(0);
249386
  }
249386
249386
  bool onPropertyChanged(std::string propertyName) override {
249386
    TypeMap::const_iterator i = m_localnameToType.find(m_assistantType.getValue());
249386
    m_newAssisnantType = i == m_localnameToType.end() ? TStringId() : i->second;
249386
    return true;
249386
  }
249386
249386
  void resetCurrentPoint() {
249386
    m_currentAssistantCreated = false;
249386
    m_currentAssistantIndex = -1;
249386
    m_currentPointIndex = -1;
249386
    m_currentPointOffset = TPointD();
249386
    m_currentAssistantBackup.reset();
249386
  }
249386
249386
  const TAssistant* findCurrentPoint(const TPointD &position) {
249386
    resetCurrentPoint();
249386
    TMetaImage *mi = dynamic_cast<tmetaimage*>(getImage(false));</tmetaimage*>
249386
    if (!mi) return NULL;
249386
249386
    double pixelSize2 = tglGetPixelSize2();
249386
    TMetaImage::Reader reader(*mi);
249386
    const TAssistant *currentAssisntant = NULL;
249386
    for(TMetaObjectRefList::const_iterator i = reader->begin(); i != reader->end(); ++i) {
249386
      if (!*i) continue;
249386
      const TAssistant *assistant = (*i)->getHandler<tassistant>();</tassistant>
249386
      if (!assistant) continue;
249386
      assistant->deselectAll();
249386
      for(int j = 0; j < assistant->pointsCount() && m_currentAssistantIndex < 0; ++j) {
249386
        const TAssistantPoint &p = assistant->points()[j];
249386
        TPointD offset = p.position - position;
249386
        if (norm2(offset) <= p.radius*p.radius*pixelSize2) {
249386
          m_currentAssistantIndex = i - reader->begin();
249386
          m_currentPointIndex = j;
249386
          m_currentPointOffset = offset;
249386
          currentAssisntant = assistant;
249386
          assistant->selectPoint(j);
249386
          break;
249386
        }
249386
      }
249386
    }
249386
    return currentAssisntant;
249386
  }
249386
249386
  void mouseMove(const TPointD &position, const TMouseEvent&) override {
249386
    if (m_dragging) return;
249386
    findCurrentPoint(position);
249386
    m_currentPosition = position;
249386
    getViewer()->GLInvalidateAll();
249386
  }
249386
249386
  void leftButtonDown(const TPointD &position, const TMouseEvent&) override {
249386
    m_dragging = true;
249386
    if (m_newAssisnantType) {
249386
      // create assistant
249386
      resetCurrentPoint();
249386
      if (TMetaImage *mi = dynamic_cast<tmetaimage*>(getImage(true))) {</tmetaimage*>
249386
        TMetaImage::Writer writer(*mi);
249386
        TMetaObjectR obj(new TMetaObject(m_newAssisnantType));
249386
        if (TAssistant *assistant = obj->getHandler<tassistant>()) {</tassistant>
249386
          if (assistant->pointsCount()) {
249386
            assistant->movePoint(0, position);
249386
            m_currentAssistantCreated = true;
249386
            m_currentAssistantIndex = (int)writer->size();
249386
            m_currentPointIndex = 0;
249386
            m_currentPointOffset = TPointD();
249386
          }
249386
          writer->push_back(obj);
249386
        }
249386
      }
249386
      m_newAssisnantType.reset();
249386
    } else
249386
    if (const TAssistant *assistant = findCurrentPoint(position)) {
249386
      m_currentAssistantBackup = assistant->data();
249386
    }
249386
    m_currentPosition = position;
249386
    getViewer()->GLInvalidateAll();
249386
  }
249386
249386
  void leftButtonDrag(const TPointD &position, const TMouseEvent&) override {
249386
    if (m_currentAssistantIndex >= 0)
249386
    if (m_currentPointIndex >= 0)
249386
    if (TMetaImage *mi = dynamic_cast<tmetaimage*>(getImage(true)))</tmetaimage*>
249386
    {
249386
      TMetaImage::Writer writer(*mi);
249386
      if (m_currentAssistantIndex < (int)writer->size())
249386
      if (TMetaObjectR obj = (*writer)[m_currentAssistantIndex])
249386
      if (TAssistant *assistant = obj->getHandler<tassistant>())</tassistant>
249386
      if (m_currentPointIndex < assistant->pointsCount())
249386
      {
249386
        assistant->movePoint(
249386
          m_currentPointIndex,
249386
          position + m_currentPointOffset);
249386
      }
249386
    }
249386
    m_currentPosition = position;
249386
    getViewer()->GLInvalidateAll();
249386
  }
249386
249386
  void leftButtonUp(const TPointD &position, const TMouseEvent&) override {
249386
    if (m_currentAssistantIndex >= 0)
249386
    if (m_currentPointIndex >= 0)
249386
    if (TMetaImage *mi = dynamic_cast<tmetaimage*>(getImage(true)))</tmetaimage*>
249386
    {
249386
      TMetaImage::Writer writer(*mi);
249386
      if (m_currentAssistantIndex < (int)writer->size())
249386
      if (TMetaObjectR obj = (*writer)[m_currentAssistantIndex])
249386
      if (TAssistant *assistant = obj->getHandler<tassistant>())</tassistant>
249386
      if (m_currentPointIndex < assistant->pointsCount())
249386
      {
249386
        assistant->movePoint(
249386
          m_currentPointIndex,
249386
          position + m_currentPointOffset);
249386
        assistant->fixData();
249386
        TUndoManager::manager()->add(new EditAssistantsUndo(
249386
          getApplication()->getCurrentLevel()->getLevel()->getSimpleLevel(),
249386
          getCurrentFid(),
249386
          m_currentAssistantCreated,
249386
          obj,
249386
          m_currentAssistantBackup ));
249386
      }
249386
    }
249386
    m_assistantType.setIndex(0);
249386
    getApplication()->getCurrentTool()->notifyToolChanged();
249386
    m_currentPosition = position;
249386
    getViewer()->GLInvalidateAll();
249386
    m_dragging = false;
249386
  }
249386
249386
  void draw() override {
249386
    m_currentGuidelines.clear();
249386
249386
    // draw assistants
249386
    TMetaImage *mi = dynamic_cast<tmetaimage*>(getImage(false));</tmetaimage*>
249386
    if (!mi) return;
249386
    TMetaImage::Reader reader(*mi);
249386
    for(TMetaObjectRefList::const_iterator i = reader->begin(); i != reader->end(); ++i)
249386
      if (*i)
249386
      if (const TAssistant *assistant = (*i)->getHandler<tassistant>())</tassistant>
249386
      {
249386
        assistant->drawEdit(getViewer());
249386
        assistant->getGuidelines(
249386
          m_currentPosition + m_currentPointOffset,
249386
          TAffine(),
249386
          m_currentGuidelines );
249386
      }
249386
249386
    // draw guidelines
249386
    for(TGuidelineList::const_iterator i = m_currentGuidelines.begin(); i != m_currentGuidelines.end(); ++i)
249386
      (*i)->draw();
249386
  }
249386
};
249386
249386
//-------------------------------------------------------------------
249386
249386
EditAssistantsTool editAssistantsTool;