Ivan Mahonin 249386
Ivan Mahonin 249386
// TnzTools includes
Ivan Mahonin 249386
#include <tools/tool.h>
Ivan Mahonin 249386
#include <tools/toolutils.h>
Ivan Mahonin 249386
#include <tools/toolhandle.h>
Ivan Mahonin 249386
#include <tools/cursors.h>
Ivan Mahonin 249386
#include <tools/assistant.h>
Ivan Mahonin 3bac66
#include <tools/inputmanager.h>
Ivan Mahonin 249386
Ivan Mahonin 249386
// TnzLib includes
Ivan Mahonin 249386
#include <toonz/tapplication.h>
Ivan Mahonin 249386
#include <toonz/txshlevelhandle.h>
Ivan Mahonin 8f7a4e
#include <toonz/txsheethandle.h>
Ivan Mahonin 249386
Ivan Mahonin 249386
// TnzCore includes
Ivan Mahonin 249386
#include <tgl.h>
Ivan Mahonin 249386
#include <tproperty.h>
Ivan Mahonin 249386
#include <tmetaimage.h>
Ivan Mahonin 249386
Ivan Mahonin 249386
// For Qt translation support
Ivan Mahonin 249386
#include <QCoreApplication>
Ivan Mahonin 249386
Ivan Mahonin 249386
#include <map>
Ivan Mahonin 249386
Ivan Mahonin 249386
Ivan Mahonin 249386
//-------------------------------------------------------------------
Ivan Mahonin 249386
Ivan Mahonin 249386
//=============================================================================
Ivan Mahonin 249386
// Edit Assistants Undo
Ivan Mahonin 249386
//-----------------------------------------------------------------------------
Ivan Mahonin 249386
Ivan Mahonin 249386
class EditAssistantsUndo final : public ToolUtils::TToolUndo {
Ivan Mahonin 249386
private:
Ivan Mahonin d94945
  bool m_isCreated;
Ivan Mahonin d94945
  bool m_isRemoved;
Ivan Mahonin c5e805
  int m_index;
Ivan Mahonin 249386
  TMetaObjectP m_metaObject;
Ivan Mahonin 249386
  TVariant m_oldData;
Ivan Mahonin 249386
  TVariant m_newData;
Ivan Mahonin 249386
  size_t m_size;
Ivan Mahonin 249386
Ivan Mahonin 249386
public:
Ivan Mahonin 249386
  EditAssistantsUndo(
Ivan Mahonin 249386
    TXshSimpleLevel *level,
Ivan Mahonin 249386
    const TFrameId &frameId,
Ivan Mahonin 8f7a4e
    bool frameCreated,
Ivan Mahonin 8f7a4e
    bool levelCreated,
Ivan Mahonin 8f7a4e
    bool objectCreated,
Ivan Mahonin 8f7a4e
    bool objectRemoved,
Ivan Mahonin c5e805
    int index,
Ivan Mahonin 3bac66
    TMetaObjectP metaObject,
Ivan Mahonin 249386
    TVariant oldData
Ivan Mahonin 249386
  ):
Ivan Mahonin 8f7a4e
    ToolUtils::TToolUndo(level, frameId, frameCreated, levelCreated),
Ivan Mahonin 8f7a4e
    m_isCreated(objectCreated),
Ivan Mahonin 8f7a4e
    m_isRemoved(objectRemoved),
Ivan Mahonin c5e805
    m_index(index),
Ivan Mahonin 3bac66
    m_metaObject(metaObject),
Ivan Mahonin 249386
    m_oldData(oldData),
Ivan Mahonin 249386
    m_newData(m_metaObject->data()),
Ivan Mahonin 249386
    m_size(m_oldData.getMemSize() + m_newData.getMemSize())
Ivan Mahonin 249386
  { }
Ivan Mahonin 249386
Ivan Mahonin 249386
  int getSize() const override
Ivan Mahonin 249386
    { return m_size; }
Ivan Mahonin 249386
  QString getToolName() override
Ivan Mahonin 249386
    { return QString("Edit Assistants Tool"); }
Ivan Mahonin 249386
Ivan Mahonin d94945
  void process(bool remove, const TVariant &data) const {
Ivan Mahonin c5e805
    if (TMetaImage *metaImage = dynamic_cast<TMetaImage*>(m_level->getFrame(m_frameId, true).getPointer())) {
Ivan Mahonin c5e805
      TMetaImage::Writer writer(*metaImage);
Ivan Mahonin c5e805
      bool found = false;
Ivan Mahonin c5e805
      for(TMetaObjectList::iterator i = writer->begin(); i != writer->end(); ++i)
Ivan Mahonin c5e805
        if ((*i) == m_metaObject) {
Ivan Mahonin c5e805
          if (remove) writer->erase(i);
Ivan Mahonin c5e805
          found = true;
Ivan Mahonin c5e805
          break;
Ivan Mahonin d94945
        }
Ivan Mahonin c5e805
      if (!remove) {
Ivan Mahonin c5e805
        if (!found)
Ivan Mahonin c5e805
          writer->insert(
Ivan Mahonin c5e805
            writer->begin() + std::max(0, std::min((int)writer->size(), m_index)),
Ivan Mahonin c5e805
            m_metaObject );
Ivan Mahonin c5e805
        m_metaObject->data() = data;
Ivan Mahonin c5e805
        if (m_metaObject->handler())
Ivan Mahonin c5e805
          m_metaObject->handler()->fixData();
Ivan Mahonin 249386
      }
Ivan Mahonin 249386
    }
Ivan Mahonin 249386
  }
Ivan Mahonin 249386
Ivan Mahonin 8f7a4e
  void undo() const override {
Ivan Mahonin 8f7a4e
    removeLevelAndFrameIfNeeded();
Ivan Mahonin 8f7a4e
    process(m_isCreated, m_oldData);
Ivan Mahonin 8f7a4e
    TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Ivan Mahonin 8f7a4e
    notifyImageChanged();
Ivan Mahonin 8f7a4e
  }
Ivan Mahonin d94945
Ivan Mahonin 8f7a4e
  void redo() const override {
Ivan Mahonin 8f7a4e
    insertLevelAndFrameIfNeeded();
Ivan Mahonin 8f7a4e
    process(m_isRemoved, m_newData);
Ivan Mahonin 8f7a4e
    TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Ivan Mahonin 8f7a4e
    notifyImageChanged();
Ivan Mahonin 8f7a4e
  }
Ivan Mahonin 249386
};
Ivan Mahonin 249386
Ivan Mahonin 249386
Ivan Mahonin 249386
//=============================================================================
Ivan Mahonin 249386
// Edit Assistants Tool
Ivan Mahonin 249386
//-----------------------------------------------------------------------------
Ivan Mahonin 249386
Ivan Mahonin 249386
class EditAssistantsTool final : public TTool {
Ivan Mahonin 249386
  Q_DECLARE_TR_FUNCTIONS(EditAssistantsTool)
Ivan Mahonin 4da757
protected:
Ivan Mahonin 3bac66
  enum Mode {
Ivan Mahonin 3bac66
    ModeImage,
Ivan Mahonin 3bac66
    ModeAssistant,
Ivan Mahonin 3bac66
    ModePoint
Ivan Mahonin 3bac66
  };
Ivan Mahonin 249386
Ivan Mahonin 3bac66
  TPropertyGroup m_allProperties;
Ivan Mahonin 3bac66
  TPropertyGroup m_toolProperties;
Ivan Mahonin 249386
  TEnumProperty m_assistantType;
Ivan Mahonin 249386
  TStringId m_newAssisnantType;
Ivan Mahonin 249386
Ivan Mahonin 249386
  bool           m_dragging;
Ivan Mahonin aedcda
  bool           m_dragAllPoints;
Ivan Mahonin 3bac66
  TMetaObjectH   m_currentAssistant;
Ivan Mahonin 249386
  bool           m_currentAssistantCreated;
Ivan Mahonin 3bac66
  bool           m_currentAssistantChanged;
Ivan Mahonin 249386
  int            m_currentAssistantIndex;
Ivan Mahonin 3bac66
  TVariant       m_currentAssistantBackup;
Ivan Mahonin c5e805
  TStringId      m_currentPointName;
Ivan Mahonin 249386
  TPointD        m_currentPointOffset;
Ivan Mahonin 249386
  TPointD        m_currentPosition;
Ivan Mahonin 249386
  TGuidelineList m_currentGuidelines;
Ivan Mahonin 249386
Ivan Mahonin 3bac66
  TMetaImage::Reader *m_reader;
Ivan Mahonin 3bac66
  TMetaImage         *m_readImage;
Ivan Mahonin 3bac66
  TMetaObjectPC       m_readObject;
Ivan Mahonin 3bac66
  const TAssistant   *m_readAssistant;
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
  TMetaImage::Writer *m_writer;
Ivan Mahonin 3bac66
  TMetaImage         *m_writeImage;
Ivan Mahonin 3bac66
  TMetaObjectP        m_writeObject;
Ivan Mahonin 3bac66
  TAssistant         *m_writeAssistant;
Ivan Mahonin 3bac66
Ivan Mahonin 249386
public:
Ivan Mahonin 249386
  EditAssistantsTool():
Ivan Mahonin 249386
    TTool("T_EditAssistants"),
Ivan Mahonin 249386
    m_assistantType("AssistantType"),
Ivan Mahonin 249386
    m_dragging(),
Ivan Mahonin aedcda
    m_dragAllPoints(),
Ivan Mahonin 249386
    m_currentAssistantCreated(),
Ivan Mahonin 3bac66
    m_currentAssistantChanged(),
Ivan Mahonin 249386
    m_currentAssistantIndex(-1),
Ivan Mahonin 3bac66
    m_reader(),
Ivan Mahonin 3bac66
    m_readImage(),
Ivan Mahonin 3bac66
    m_readAssistant(),
Ivan Mahonin 3bac66
    m_writer(),
Ivan Mahonin 3bac66
    m_writeImage(),
Ivan Mahonin 3bac66
    m_writeAssistant()
Ivan Mahonin 249386
  {
Ivan Mahonin 66ffab
    bind(MetaImage | EmptyTarget);
Ivan Mahonin 3bac66
    m_toolProperties.bind(m_assistantType);
Ivan Mahonin 249386
    updateTranslation();
Ivan Mahonin 249386
  }
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
  ~EditAssistantsTool()
Ivan Mahonin 3bac66
    { close(); }
Ivan Mahonin 3bac66
Ivan Mahonin 249386
  ToolType getToolType() const override
Ivan Mahonin 249386
    { return TTool::LevelWriteTool; }
Ivan Mahonin 249386
  int getCursorId() const override
Ivan Mahonin 249386
    { return ToolCursor::StrokeSelectCursor; }
Ivan Mahonin 249386
  void onImageChanged() override
Ivan Mahonin 249386
    { getViewer()->GLInvalidateAll(); }
Ivan Mahonin 249386
Ivan Mahonin 4da757
  void updateAssistantTypes() {
Ivan Mahonin 4da757
    std::wstring value = m_assistantType.getValue();
Ivan Mahonin 4da757
Ivan Mahonin 4da757
    m_assistantType.deleteAllValues();
Ivan Mahonin 4da757
    m_assistantType.addValueWithUIName(L"", tr("--"));
Ivan Mahonin 4da757
Ivan Mahonin 4da757
    const TMetaObject::Registry &registry = TMetaObject::getRegistry();
Ivan Mahonin 4da757
    for(TMetaObject::Registry::const_iterator i = registry.begin(); i != registry.end(); ++i)
Ivan Mahonin 4da757
      if (const TAssistantType *assistantType = dynamic_cast<const TAssistantType*>(i->second))
Ivan Mahonin 4da757
        if (assistantType->name)
Ivan Mahonin 4da757
          m_assistantType.addValueWithUIName(
Ivan Mahonin 4da757
            to_wstring(assistantType->name.str()),
Ivan Mahonin 4da757
            assistantType->getLocalName() );
Ivan Mahonin 4da757
Ivan Mahonin 4da757
    if (m_assistantType.indexOf(value) >= 0)
Ivan Mahonin 4da757
      m_assistantType.setValue(value);
Ivan Mahonin 4da757
  }
Ivan Mahonin 4da757
Ivan Mahonin 3bac66
  TPropertyGroup* getProperties(int) override {
Ivan Mahonin 3bac66
    m_allProperties.clear();
Ivan Mahonin 3bac66
    for(int i = 0; i < m_toolProperties.getPropertyCount(); ++i)
Ivan Mahonin 3bac66
      m_allProperties.bind( *m_toolProperties.getProperty(i) );
Ivan Mahonin 3bac66
    if (Closer closer = read(ModeAssistant)) {
Ivan Mahonin 4da757
      m_readAssistant->updateTranslation();
Ivan Mahonin 3bac66
      TPropertyGroup &assistantProperties = m_readAssistant->getProperties();
Ivan Mahonin 3bac66
      for(int i = 0; i < assistantProperties.getPropertyCount(); ++i)
Ivan Mahonin 3bac66
        m_allProperties.bind( *assistantProperties.getProperty(i) );
Ivan Mahonin 3bac66
    }
Ivan Mahonin 3bac66
    return &m_allProperties;
Ivan Mahonin 3bac66
  }
Ivan Mahonin 3bac66
Ivan Mahonin 4da757
  void onActivate() override
Ivan Mahonin 4da757
    { updateAssistantTypes(); }
Ivan Mahonin 249386
Ivan Mahonin 249386
  void updateTranslation() override {
Ivan Mahonin 4da757
    m_assistantType.setQStringName( tr("Assistant Type") );
Ivan Mahonin 4da757
    updateAssistantTypes();
Ivan Mahonin 4da757
    if (Closer closer = read(ModeAssistant))
Ivan Mahonin 4da757
      m_readAssistant->updateTranslation();
Ivan Mahonin 249386
  }
Ivan Mahonin 249386
Ivan Mahonin d07d8b
  bool onPropertyChanged(std::string name, bool addToUndo) override {
Ivan Mahonin 3bac66
    if (TProperty *property = m_toolProperties.getProperty(name)) {
Ivan Mahonin 3bac66
      if (name == m_assistantType.getName())
Ivan Mahonin 3bac66
        m_newAssisnantType = TStringId::find( to_string(m_assistantType.getValue()) );
Ivan Mahonin 3bac66
    } else {
Ivan Mahonin 3bac66
      if (Closer closer = write(ModeAssistant, true))
Ivan Mahonin 3bac66
        m_writeAssistant->propertyChanged(TStringId::find(name));
Ivan Mahonin d07d8b
      if (addToUndo) apply();
Ivan Mahonin 3bac66
      getViewer()->GLInvalidateAll();
Ivan Mahonin 3bac66
    }
Ivan Mahonin 249386
    return true;
Ivan Mahonin 249386
  }
Ivan Mahonin 249386
Ivan Mahonin 3bac66
protected:
Ivan Mahonin 3bac66
  void close() {
Ivan Mahonin 3bac66
    m_readAssistant = 0;
Ivan Mahonin 3bac66
    m_readObject.reset();
Ivan Mahonin 3bac66
    m_readImage = 0;
Ivan Mahonin 3bac66
    if (m_reader) delete(m_reader);
Ivan Mahonin 3bac66
    m_reader = 0;
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
    m_writeAssistant = 0;
Ivan Mahonin 3bac66
    m_writeObject.reset();
Ivan Mahonin 3bac66
    m_writeImage = 0;
Ivan Mahonin 3bac66
    if (m_writer) delete(m_writer);
Ivan Mahonin 3bac66
    m_writer = 0;
Ivan Mahonin 3bac66
  }
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
  bool openRead(Mode mode) {
Ivan Mahonin 3bac66
    close();
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
    if ( (mode >= ModeAssistant && !m_currentAssistant)
Ivan Mahonin 3bac66
      || (mode >= ModeAssistant && m_currentAssistantIndex < 0)
Ivan Mahonin c5e805
      || (mode >= ModePoint && !m_currentPointName) ) return false;
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
    m_readImage = dynamic_cast<TMetaImage*>(getImage(true));
Ivan Mahonin 3bac66
    if (m_readImage) {
Ivan Mahonin 3bac66
      m_reader = new TMetaImage::Reader(*m_readImage);
Ivan Mahonin 3bac66
      if (mode == ModeImage) return true;
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
      if ( m_currentAssistantIndex < (int)(*m_reader)->size()
Ivan Mahonin 3bac66
        && (**m_reader)[m_currentAssistantIndex] == m_currentAssistant )
Ivan Mahonin 3bac66
      {
Ivan Mahonin 3bac66
        m_readObject = (**m_reader)[m_currentAssistantIndex];
Ivan Mahonin 3bac66
        m_readAssistant = m_readObject->getHandler<TAssistant>();
Ivan Mahonin 3bac66
        if (mode == ModeAssistant) return true;
Ivan Mahonin 3bac66
Ivan Mahonin c5e805
        if (m_readAssistant->findPoint(m_currentPointName)) {
Ivan Mahonin 3bac66
          if (mode == ModePoint) return true;
Ivan Mahonin 3bac66
        }
Ivan Mahonin 3bac66
      }
Ivan Mahonin 3bac66
    }
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
    close();
Ivan Mahonin 3bac66
    return false;
Ivan Mahonin 3bac66
  }
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
  void touch() {
Ivan Mahonin 3bac66
    if (m_writeAssistant && !m_currentAssistantChanged) {
Ivan Mahonin 3bac66
      m_currentAssistantBackup = m_writeAssistant->data();
Ivan Mahonin 3bac66
      m_currentAssistantChanged = true;
Ivan Mahonin 3bac66
    }
Ivan Mahonin 3bac66
  }
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
  bool openWrite(Mode mode, bool touch = false) {
Ivan Mahonin 3bac66
    close();
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
    if ( (mode >= ModeAssistant && !m_currentAssistant)
Ivan Mahonin 3bac66
      || (mode >= ModeAssistant && m_currentAssistantIndex < 0)
Ivan Mahonin c5e805
      || (mode >= ModePoint && !m_currentPointName) ) return false;
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
    m_writeImage = dynamic_cast<TMetaImage*>(getImage(true));
Ivan Mahonin 3bac66
    if (m_writeImage) {
Ivan Mahonin 3bac66
      m_writer = new TMetaImage::Writer(*m_writeImage);
Ivan Mahonin 3bac66
      if (mode == ModeImage) return true;
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
      if ( m_currentAssistantIndex < (int)(*m_writer)->size()
Ivan Mahonin 3bac66
        && (**m_writer)[m_currentAssistantIndex] == m_currentAssistant )
Ivan Mahonin 3bac66
      {
Ivan Mahonin 3bac66
        m_writeObject = (**m_writer)[m_currentAssistantIndex];
Ivan Mahonin 3bac66
        m_writeAssistant = m_writeObject->getHandler<TAssistant>();
Ivan Mahonin 3bac66
        if ( (mode == ModeAssistant)
Ivan Mahonin c5e805
          || (mode == ModePoint && m_writeAssistant->findPoint(m_currentPointName)) )
Ivan Mahonin 3bac66
        {
Ivan Mahonin 3bac66
          if (touch) this->touch();
Ivan Mahonin 3bac66
          return true;
Ivan Mahonin 3bac66
        }
Ivan Mahonin 3bac66
      }
Ivan Mahonin 3bac66
    }
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
    close();
Ivan Mahonin 3bac66
    return false;
Ivan Mahonin 3bac66
  }
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
  //! helper functions for construction like this:
Ivan Mahonin 3bac66
  //!   if (Closer closer = read(ModeAssistant)) { do-something... }
Ivan Mahonin 3bac66
  struct Closer {
Ivan Mahonin 3bac66
    struct Args {
Ivan Mahonin 3bac66
      EditAssistantsTool *owner;
Ivan Mahonin 3bac66
      Args(EditAssistantsTool &owner): owner(&owner) { }
Ivan Mahonin 3bac66
      operator bool() const //!< declare bool-convertor here to prevent convertion path: Args->Closer->bool
Ivan Mahonin 3bac66
        { return owner && (owner->m_reader || owner->m_writer); }
Ivan Mahonin 3bac66
      void close()
Ivan Mahonin 3bac66
        { if (owner) owner->close(); }
Ivan Mahonin 3bac66
    };
Ivan Mahonin 3bac66
    Closer(const Args &args): args(args) { }
Ivan Mahonin 3bac66
    ~Closer() { args.close(); }
Ivan Mahonin 3bac66
    operator bool() const { return args; }
Ivan Mahonin 3bac66
  private:
Ivan Mahonin 3bac66
    Args args;
Ivan Mahonin 3bac66
  };
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
  Closer::Args read(Mode mode)
Ivan Mahonin 3bac66
    { openRead(mode); return Closer::Args(*this); }
Ivan Mahonin 3bac66
  Closer::Args write(Mode mode, bool touch = false)
Ivan Mahonin 3bac66
    { openWrite(mode, touch); return Closer::Args(*this); }
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
  void updateOptionsBox()
Ivan Mahonin cbbe07
    { getApplication()->getCurrentTool()->notifyToolOptionsBoxChanged(); }
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
  void resetCurrentPoint(bool updateOptionsBox = true) {
Ivan Mahonin 3bac66
    close();
Ivan Mahonin 3bac66
    m_currentAssistant.reset();
Ivan Mahonin 249386
    m_currentAssistantCreated = false;
Ivan Mahonin 3bac66
    m_currentAssistantChanged = false;
Ivan Mahonin 249386
    m_currentAssistantIndex = -1;
Ivan Mahonin c5e805
    m_currentPointName.reset();
Ivan Mahonin 249386
    m_currentPointOffset = TPointD();
Ivan Mahonin 249386
    m_currentAssistantBackup.reset();
Ivan Mahonin 3bac66
    if (updateOptionsBox) this->updateOptionsBox();
Ivan Mahonin 249386
  }
Ivan Mahonin 249386
Ivan Mahonin 3bac66
  bool findCurrentPoint(const TPointD &position, double pixelSize = 1, bool updateOptionsBox = true) {
Ivan Mahonin 3bac66
    resetCurrentPoint(false);
Ivan Mahonin 3bac66
    if (Closer closer = read(ModeImage)) {
Ivan Mahonin 3bac66
      for(TMetaObjectListCW::iterator i = (*m_reader)->begin(); i != (*m_reader)->end(); ++i) {
Ivan Mahonin 3bac66
        if (!*i) continue;
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
        const TAssistant *assistant = (*i)->getHandler<TAssistant>();
Ivan Mahonin 3bac66
        if (!assistant) continue;
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
        assistant->deselectAll();
Ivan Mahonin 7900ea
Ivan Mahonin 7900ea
        // last points is less significant and don't affecting the first points
Ivan Mahonin 7900ea
        // so iterate points in reverse order to avoid unsolvable points overlapping
Ivan Mahonin 7900ea
        const TAssistantPointOrder &points = assistant->pointsOrder();
Ivan Mahonin 7900ea
        for( TAssistantPointOrder::const_reverse_iterator j = points.rbegin();
Ivan Mahonin 7900ea
             j != points.rend() && m_currentAssistantIndex < 0;
Ivan Mahonin 7900ea
             ++j )
Ivan Mahonin 7900ea
        {
Ivan Mahonin 7900ea
          const TAssistantPoint &p = **j;
Ivan Mahonin 3bac66
          TPointD offset = p.position - position;
Ivan Mahonin c5e805
          if (p.visible && norm2(offset) <= p.radius*p.radius*pixelSize*pixelSize) {
Ivan Mahonin 3bac66
            m_currentAssistant.set(*i);
Ivan Mahonin 3bac66
            m_currentAssistantIndex = i - (*m_reader)->begin();
Ivan Mahonin 7900ea
            m_currentPointName = p.name;
Ivan Mahonin 3bac66
            m_currentPointOffset = offset;
Ivan Mahonin 3bac66
            assistant->selectAll();
Ivan Mahonin 3bac66
          }
Ivan Mahonin 249386
        }
Ivan Mahonin 249386
      }
Ivan Mahonin 249386
    }
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
    if (updateOptionsBox) this->updateOptionsBox();
Ivan Mahonin 3bac66
    return m_currentAssistantIndex >= 0;
Ivan Mahonin 249386
  }
Ivan Mahonin 249386
Ivan Mahonin 3bac66
  bool apply() {
Ivan Mahonin 3bac66
    bool success = false;
Ivan Mahonin 3bac66
    if (m_currentAssistantChanged || m_currentAssistantCreated) {
Ivan Mahonin 7900ea
      if (Closer closer = write(ModeAssistant)) {
Ivan Mahonin 3bac66
        m_writeAssistant->fixData();
Ivan Mahonin 3bac66
        TUndoManager::manager()->add(new EditAssistantsUndo(
Ivan Mahonin 3bac66
          getApplication()->getCurrentLevel()->getLevel()->getSimpleLevel(),
Ivan Mahonin 3bac66
          getCurrentFid(),
Ivan Mahonin 8f7a4e
          m_isFrameCreated,
Ivan Mahonin 8f7a4e
          m_isLevelCreated,
Ivan Mahonin 3bac66
          m_currentAssistantCreated,
Ivan Mahonin 3bac66
          false,
Ivan Mahonin c5e805
          m_currentAssistantIndex,
Ivan Mahonin 3bac66
          m_writeObject,
Ivan Mahonin 3bac66
          m_currentAssistantBackup ));
Ivan Mahonin 3bac66
        m_currentAssistantCreated = false;
Ivan Mahonin 3bac66
        m_currentAssistantChanged = false;
Ivan Mahonin 8f7a4e
        m_isFrameCreated = false;
Ivan Mahonin 8f7a4e
        m_isLevelCreated = false;
Ivan Mahonin 3bac66
        success = true;
Ivan Mahonin 3bac66
      }
Ivan Mahonin 3bac66
    }
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
    if (success) {
Ivan Mahonin 3bac66
      notifyImageChanged();
Ivan Mahonin 3bac66
      getApplication()->getCurrentTool()->notifyToolChanged();
Ivan Mahonin 3bac66
      getViewer()->GLInvalidateAll();
Ivan Mahonin 3bac66
    }
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
    return success;
Ivan Mahonin 249386
  }
Ivan Mahonin 249386
Ivan Mahonin 8f7a4e
public:
Ivan Mahonin 8f7a4e
  bool preLeftButtonDown() override {
Ivan Mahonin 8f7a4e
    touchImage();
Ivan Mahonin 8f7a4e
    return true;
Ivan Mahonin 8f7a4e
  }
Ivan Mahonin 8f7a4e
Ivan Mahonin aedcda
  void leftButtonDown(const TPointD &position, const TMouseEvent &event) override {
Ivan Mahonin 3bac66
    apply();
Ivan Mahonin 249386
    m_dragging = true;
Ivan Mahonin aedcda
    m_dragAllPoints = false;
Ivan Mahonin 249386
    if (m_newAssisnantType) {
Ivan Mahonin 249386
      // create assistant
Ivan Mahonin 7900ea
      resetCurrentPoint(false);
Ivan Mahonin 3bac66
      if (Closer closer = write(ModeImage)) {
Ivan Mahonin 3bac66
        TMetaObjectP object(new TMetaObject(m_newAssisnantType));
Ivan Mahonin 3bac66
        if (TAssistant *assistant = object->getHandler<TAssistant>()) {
Ivan Mahonin c5e805
          assistant->setDefaults();
Ivan Mahonin 7900ea
          assistant->move(position);
Ivan Mahonin 7900ea
          assistant->selectAll();
Ivan Mahonin aedcda
          m_dragAllPoints = true;
Ivan Mahonin c5e805
          m_currentAssistantCreated = true;
Ivan Mahonin c5e805
          m_currentAssistantChanged = true;
Ivan Mahonin c5e805
          m_currentAssistantIndex = (int)(*m_writer)->size();
Ivan Mahonin c5e805
          m_currentAssistant = object;
Ivan Mahonin c5e805
          m_currentPointName = assistant->getBasePoint().name;
Ivan Mahonin c5e805
          m_currentPointOffset = TPointD();
Ivan Mahonin c5e805
          m_currentAssistantBackup = assistant->data();
Ivan Mahonin 3bac66
          (*m_writer)->push_back(object);
Ivan Mahonin 249386
        }
Ivan Mahonin 249386
      }
Ivan Mahonin 7900ea
      updateOptionsBox();
Ivan Mahonin 249386
      m_newAssisnantType.reset();
Ivan Mahonin 3bac66
    } else {
Ivan Mahonin 3bac66
      findCurrentPoint(position);
Ivan Mahonin aedcda
      if (event.isShiftPressed())
Ivan Mahonin aedcda
        if (Closer closer = read(ModePoint)) {
Ivan Mahonin aedcda
          m_currentPointName = m_readAssistant->getBasePoint().name;
Ivan Mahonin aedcda
          m_currentPointOffset = m_readAssistant->getBasePoint().position - position;
Ivan Mahonin aedcda
          m_dragAllPoints = true;
Ivan Mahonin aedcda
        }
Ivan Mahonin 249386
    }
Ivan Mahonin 3bac66
Ivan Mahonin 249386
    m_currentPosition = position;
Ivan Mahonin 249386
    getViewer()->GLInvalidateAll();
Ivan Mahonin 249386
  }
Ivan Mahonin 249386
Ivan Mahonin 249386
  void leftButtonDrag(const TPointD &position, const TMouseEvent&) override {
Ivan Mahonin aedcda
    if (m_dragAllPoints) {
Ivan Mahonin 7900ea
      if (Closer closer = write(ModeAssistant, true))
Ivan Mahonin 7900ea
        m_writeAssistant->move( position + m_currentPointOffset );
Ivan Mahonin 7900ea
    } else {
Ivan Mahonin 7900ea
      if (Closer closer = write(ModePoint, true))
Ivan Mahonin 7900ea
        m_writeAssistant->movePoint(
Ivan Mahonin 7900ea
          m_currentPointName,
Ivan Mahonin 7900ea
          position + m_currentPointOffset);
Ivan Mahonin 7900ea
    }
Ivan Mahonin 249386
    m_currentPosition = position;
Ivan Mahonin 249386
    getViewer()->GLInvalidateAll();
Ivan Mahonin 249386
  }
Ivan Mahonin 249386
Ivan Mahonin 249386
  void leftButtonUp(const TPointD &position, const TMouseEvent&) override {
Ivan Mahonin 7900ea
    if (m_currentAssistantCreated) {
Ivan Mahonin aedcda
      if (Closer closer = write(ModeAssistant, true)) {
Ivan Mahonin aedcda
        m_writeAssistant->getBasePoint();
Ivan Mahonin 7900ea
        m_writeAssistant->move( position + m_currentPointOffset );
Ivan Mahonin aedcda
      }
Ivan Mahonin 7900ea
    } else {
Ivan Mahonin 7900ea
      if (Closer closer = write(ModePoint, true))
Ivan Mahonin 7900ea
        m_writeAssistant->movePoint(
Ivan Mahonin 7900ea
          m_currentPointName,
Ivan Mahonin 7900ea
          position + m_currentPointOffset);
Ivan Mahonin 7900ea
    }
Ivan Mahonin 3bac66
Ivan Mahonin 3bac66
    apply();
Ivan Mahonin d94945
    m_assistantType.setIndex(0);
Ivan Mahonin 249386
    getApplication()->getCurrentTool()->notifyToolChanged();
Ivan Mahonin 3bac66
    emit getApplication()->getCurrentTool()->toolChanged();
Ivan Mahonin 249386
    m_currentPosition = position;
Ivan Mahonin 249386
    getViewer()->GLInvalidateAll();
Ivan Mahonin aedcda
    m_dragAllPoints = false;
Ivan Mahonin 249386
    m_dragging = false;
Ivan Mahonin 249386
  }
Ivan Mahonin 249386
Ivan Mahonin 3bac66
  bool keyDown(QKeyEvent *keyEvent) override {
Ivan Mahonin 9f1018
    if (keyEvent->key() == Qt::Key_Backspace) {
Ivan Mahonin 3bac66
      if (!m_dragging) {
Ivan Mahonin 3bac66
        apply();
Ivan Mahonin 3bac66
        bool success = false;
Ivan Mahonin 3bac66
        if (Closer closer = write(ModeAssistant, true)) {
Ivan Mahonin 3bac66
          (*m_writer)->erase((*m_writer)->begin() + m_currentAssistantIndex);
Ivan Mahonin 3bac66
          TUndoManager::manager()->add(new EditAssistantsUndo(
Ivan Mahonin 3bac66
            getApplication()->getCurrentLevel()->getLevel()->getSimpleLevel(),
Ivan Mahonin 3bac66
            getCurrentFid(),
Ivan Mahonin 8f7a4e
            false, // frameCreated
Ivan Mahonin 8f7a4e
            false, // levelCreated
Ivan Mahonin 8f7a4e
            false, // objectCreated
Ivan Mahonin 8f7a4e
            true,  // objectRemoved
Ivan Mahonin c5e805
            m_currentAssistantIndex,
Ivan Mahonin 3bac66
            m_writeObject,
Ivan Mahonin 3bac66
            m_writeObject->data() ));
Ivan Mahonin 3bac66
          success = true;
Ivan Mahonin d94945
        }
Ivan Mahonin 3bac66
Ivan Mahonin 8f7a4e
        if (success)
Ivan Mahonin 3bac66
          notifyImageChanged();
Ivan Mahonin 3bac66
Ivan Mahonin d94945
        resetCurrentPoint();
Ivan Mahonin d94945
        getApplication()->getCurrentTool()->notifyToolChanged();
Ivan Mahonin d94945
        getViewer()->GLInvalidateAll();
Ivan Mahonin d94945
      }
Ivan Mahonin d94945
      return true;
Ivan Mahonin d94945
    }
Ivan Mahonin d94945
    return false;
Ivan Mahonin d94945
  }
Ivan Mahonin d94945
Ivan Mahonin 249386
  void draw() override {
Ivan Mahonin 249386
    m_currentGuidelines.clear();
Ivan Mahonin 249386
Ivan Mahonin 249386
    // draw assistants
Ivan Mahonin 3bac66
    if (Closer closer = read(ModeImage))
Ivan Mahonin 3bac66
    for(TMetaObjectListCW::iterator i = (*m_reader)->begin(); i != (*m_reader)->end(); ++i)
Ivan Mahonin 249386
      if (*i)
Ivan Mahonin 249386
      if (const TAssistant *assistant = (*i)->getHandler<TAssistant>())
Ivan Mahonin 249386
      {
Ivan Mahonin 249386
        assistant->drawEdit(getViewer());
Ivan Mahonin 249386
        assistant->getGuidelines(
Ivan Mahonin 249386
          m_currentPosition + m_currentPointOffset,
Ivan Mahonin 249386
          TAffine(),
Ivan Mahonin 249386
          m_currentGuidelines );
Ivan Mahonin 249386
      }
Ivan Mahonin 249386
Ivan Mahonin 249386
    // draw guidelines
Ivan Mahonin 249386
    for(TGuidelineList::const_iterator i = m_currentGuidelines.begin(); i != m_currentGuidelines.end(); ++i)
Ivan Mahonin 249386
      (*i)->draw();
Ivan Mahonin 249386
  }
Ivan Mahonin 249386
};
Ivan Mahonin 249386
Ivan Mahonin 249386
//-------------------------------------------------------------------
Ivan Mahonin 249386
Ivan Mahonin 249386
EditAssistantsTool editAssistantsTool;