| |
| |
| #include <tools/tool.h> |
| #include <tools/toolutils.h> |
| #include <tools/toolhandle.h> |
| #include <tools/cursors.h> |
| #include <tools/assistant.h> |
| #include <tools/replicator.h> |
| #include <tools/inputmanager.h> |
| |
| |
| #include <toonz/tapplication.h> |
| #include <toonz/txshlevelhandle.h> |
| #include <toonz/txsheethandle.h> |
| #include <toonz/tframehandle.h> |
| #include <toonz/dpiscale.h> |
| |
| |
| #include <tgl.h> |
| #include <tproperty.h> |
| #include <tmetaimage.h> |
| |
| #include <toonzqt/selection.h> |
| #include <toonzqt/selectioncommandids.h> |
| #include <toonzqt/tselectionhandle.h> |
| |
| |
| #include <QCoreApplication> |
| |
| #include <map> |
| |
| |
| |
| |
| |
| |
| |
| |
| class EditAssistantsReorderUndo final : public ToolUtils::TToolUndo { |
| private: |
| int m_oldPos; |
| int m_newPos; |
| |
| public: |
| EditAssistantsReorderUndo( |
| TXshSimpleLevel *level, |
| const TFrameId &frameId, |
| int m_oldPos, |
| int m_newPos |
| ): |
| ToolUtils::TToolUndo(level, frameId), |
| m_oldPos(m_oldPos), |
| m_newPos(m_newPos) |
| { } |
| |
| QString getToolName() override |
| { return QString("Edit Assistants Tool"); } |
| |
| int getSize() const override |
| { return sizeof(*this); } |
| |
| void process(int oldPos, int newPos) const { |
| if (oldPos == newPos || oldPos < 0 || newPos < 0) |
| return; |
| TMetaImage *metaImage = dynamic_cast<TMetaImage*>(m_level->getFrame(m_frameId, true).getPointer()); |
| if (!metaImage) |
| return; |
| |
| TMetaImage::Writer writer(*metaImage); |
| TMetaObjectList &list = *writer; |
| if (oldPos >= list.size() || newPos >= writer->size()) |
| return; |
| |
| TMetaObjectP obj = list[oldPos]; |
| list.erase(list.begin() + oldPos); |
| list.insert(list.begin() + newPos, obj); |
| } |
| |
| void undo() const override { |
| process(m_newPos, m_oldPos); |
| TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged(); |
| notifyImageChanged(); |
| } |
| |
| void redo() const override { |
| process(m_oldPos, m_newPos); |
| TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged(); |
| notifyImageChanged(); |
| } |
| }; |
| |
| |
| |
| |
| |
| |
| class EditAssistantsUndo final : public ToolUtils::TToolUndo { |
| private: |
| bool m_isCreated; |
| bool m_isRemoved; |
| int m_index; |
| TMetaObjectP m_metaObject; |
| TVariant m_oldData; |
| TVariant m_newData; |
| size_t m_size; |
| |
| public: |
| EditAssistantsUndo( |
| TXshSimpleLevel *level, |
| const TFrameId &frameId, |
| bool frameCreated, |
| bool levelCreated, |
| bool objectCreated, |
| bool objectRemoved, |
| int index, |
| TMetaObjectP metaObject, |
| TVariant oldData |
| ): |
| ToolUtils::TToolUndo(level, frameId, frameCreated, levelCreated), |
| m_isCreated(objectCreated), |
| m_isRemoved(objectRemoved), |
| m_index(index), |
| m_metaObject(metaObject), |
| m_oldData(oldData), |
| m_newData(m_metaObject->data()), |
| m_size(sizeof(*this) + m_oldData.getMemSize() + m_newData.getMemSize()) |
| { } |
| |
| int getSize() const override |
| { return m_size; } |
| QString getToolName() override |
| { return QString("Edit Assistants Tool"); } |
| |
| void process(bool remove, const TVariant &data) const { |
| if (TMetaImage *metaImage = dynamic_cast<TMetaImage*>(m_level->getFrame(m_frameId, true).getPointer())) { |
| TMetaImage::Writer writer(*metaImage); |
| bool found = false; |
| for(TMetaObjectList::iterator i = writer->begin(); i != writer->end(); ++i) |
| if ((*i) == m_metaObject) { |
| if (remove) writer->erase(i); |
| found = true; |
| break; |
| } |
| if (!remove) { |
| if (!found) |
| writer->insert( |
| writer->begin() + std::max(0, std::min((int)writer->size(), m_index)), |
| m_metaObject ); |
| m_metaObject->data() = data; |
| if (m_metaObject->handler()) |
| m_metaObject->handler()->fixData(); |
| } |
| } |
| } |
| |
| void undo() const override { |
| removeLevelAndFrameIfNeeded(); |
| process(m_isCreated, m_oldData); |
| TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged(); |
| notifyImageChanged(); |
| } |
| |
| void redo() const override { |
| insertLevelAndFrameIfNeeded(); |
| process(m_isRemoved, m_newData); |
| TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged(); |
| notifyImageChanged(); |
| } |
| }; |
| |
| |
| |
| |
| |
| |
| class EditAssistantsTool final : public TTool { |
| Q_DECLARE_TR_FUNCTIONS(EditAssistantsTool) |
| public: |
| class Selection final : public TSelection { |
| private: |
| EditAssistantsTool &tool; |
| public: |
| explicit Selection(EditAssistantsTool &tool): |
| tool(tool) { } |
| void deleteSelection() |
| { tool.removeSelected(); } |
| |
| void enableCommands() override |
| { if (!isEmpty()) enableCommand(this, MI_Clear, &Selection::deleteSelection); } |
| bool isEmpty() const override |
| { return !tool.isSelected(); } |
| void selectNone() override |
| { tool.deselect(); } |
| }; |
| |
| protected: |
| enum Mode { |
| ModeImage, |
| ModeAssistant, |
| ModePoint |
| }; |
| |
| TPropertyGroup m_allProperties; |
| TPropertyGroup m_toolProperties; |
| TEnumProperty m_assistantType; |
| TIntProperty m_replicatorIndex; |
| TStringId m_newAssisnantType; |
| |
| bool m_dragging; |
| bool m_dragAllPoints; |
| TSmartHolderT<TImage> m_currentImage; |
| TMetaObjectH m_currentAssistant; |
| bool m_currentAssistantCreated; |
| bool m_currentAssistantChanged; |
| int m_currentAssistantIndex; |
| TVariant m_currentAssistantBackup; |
| TStringId m_currentPointName; |
| TPointD m_currentPointOffset; |
| TPointD m_currentPosition; |
| TGuidelineList m_currentGuidelines; |
| |
| TReplicator::PointList m_replicatorPoints; |
| |
| TMetaImage::Reader *m_reader; |
| TMetaImage *m_readImage; |
| TMetaObjectPC m_readObject; |
| const TAssistantBase *m_readAssistant; |
| |
| TMetaImage::Writer *m_writer; |
| TMetaImage *m_writeImage; |
| TMetaObjectP m_writeObject; |
| TAssistantBase *m_writeAssistant; |
| |
| Selection *selection; |
| |
| |
| typedef std::pair<const void*, int> HistoryItem; |
| typedef std::vector<HistoryItem> History; |
| History m_history; |
| |
| public: |
| EditAssistantsTool(): |
| TTool("T_EditAssistants"), |
| m_assistantType("AssistantType"), |
| m_replicatorIndex("ReplicatorIndex", 1, 10, 1, false), |
| m_dragging(), |
| m_dragAllPoints(), |
| m_currentAssistantCreated(), |
| m_currentAssistantChanged(), |
| m_currentAssistantIndex(-1), |
| m_reader(), |
| m_readImage(), |
| m_readAssistant(), |
| m_writer(), |
| m_writeImage(), |
| m_writeAssistant() |
| { |
| selection = new Selection(*this); |
| |
| bind(MetaImage | EmptyTarget, "T_Brush"); |
| m_toolProperties.bind(m_assistantType); |
| m_replicatorIndex.setSpinner(); |
| updateTranslation(); |
| } |
| |
| ~EditAssistantsTool() { |
| close(); |
| delete selection; |
| } |
| |
| ToolType getToolType() const override |
| { return TTool::LevelWriteTool; } |
| unsigned int getToolHints() const override |
| { return TTool::getToolHints() & ~(HintAssistantsAll | HintReplicatorsAll); } |
| int getCursorId() const override |
| { return ToolCursor::StrokeSelectCursor; } |
| void onImageChanged() override { |
| if (m_currentImage != getImage(false)) loadHistory(); |
| getViewer()->GLInvalidateAll(); |
| } |
| |
| void updateAssistantTypes() { |
| std::wstring value = m_assistantType.getValue(); |
| |
| m_assistantType.deleteAllValues(); |
| m_assistantType.addValueWithUIName(L"", tr("<choose to create>")); |
| |
| const TMetaObject::Registry ®istry = TMetaObject::getRegistry(); |
| for(TMetaObject::Registry::const_iterator i = registry.begin(); i != registry.end(); ++i) |
| if (const TAssistantType *assistantType = dynamic_cast<const TAssistantType*>(i->second)) |
| if (assistantType->name) |
| m_assistantType.addValueWithUIName( |
| to_wstring(assistantType->name.str()), |
| assistantType->getLocalName() ); |
| |
| if (m_assistantType.indexOf(value) >= 0) |
| m_assistantType.setValue(value); |
| } |
| |
| TPropertyGroup* getProperties(int) override { |
| m_allProperties.clear(); |
| for(int i = 0; i < m_toolProperties.getPropertyCount(); ++i) |
| m_allProperties.bind( *m_toolProperties.getProperty(i) ); |
| if (Closer closer = read(ModeAssistant)) { |
| m_readAssistant->updateTranslation(); |
| if (int i = readReplicatorIndex(*m_reader)) { |
| m_replicatorIndex.setValue(i); |
| m_allProperties.bind( m_replicatorIndex ); |
| } |
| TPropertyGroup &assistantProperties = m_readAssistant->getProperties(); |
| for(int i = 0; i < assistantProperties.getPropertyCount(); ++i) |
| m_allProperties.bind( *assistantProperties.getProperty(i) ); |
| } |
| return &m_allProperties; |
| } |
| |
| void onActivate() override { |
| updateAssistantTypes(); |
| loadHistory(); |
| } |
| |
| void onDeactivate() override |
| { resetCurrentPoint(true, false); } |
| |
| void updateTranslation() override { |
| m_assistantType.setQStringName( tr("Assistant Type") ); |
| m_replicatorIndex.setQStringName( tr("Order") ); |
| updateAssistantTypes(); |
| if (Closer closer = read(ModeAssistant)) |
| m_readAssistant->updateTranslation(); |
| } |
| |
| bool onPropertyChanged(std::string name, bool addToUndo) override { |
| if (m_replicatorIndex.getName() == name) { |
| writeReplicatorIndex(m_replicatorIndex.getValue()); |
| } else |
| if (name == m_assistantType.getName()) { |
| m_newAssisnantType = TStringId::find( to_string(m_assistantType.getValue()) ); |
| } else { |
| if (Closer closer = write(ModeAssistant, true)) |
| m_writeAssistant->propertyChanged(TStringId::find(name)); |
| if (addToUndo) apply(); |
| getViewer()->GLInvalidateAll(); |
| } |
| return true; |
| } |
| |
| TSelection* getSelection() override |
| { return isSelected() ? selection : 0; } |
| |
| protected: |
| void putHistory(const void *img, int assistantIndex) { |
| if (!img) return; |
| for(History::iterator i = m_history.begin(); i != m_history.end(); ) |
| if (i->first == img) i = m_history.erase(i); else ++i; |
| if (m_history.size() >= 10) m_history.pop_back(); |
| m_history.push_back(HistoryItem(img, assistantIndex)); |
| } |
| |
| void loadHistory() { |
| int index = -1; |
| if (Closer closer = read(ModeImage)) |
| for(History::iterator i = m_history.begin(); i != m_history.end(); ++i) |
| if (i->first == m_readImage) index = i->second; |
| if (index < 0) resetCurrentPoint(true, false); else chooseAssistant(index); |
| } |
| |
| void close() { |
| m_readAssistant = 0; |
| m_readObject.reset(); |
| m_readImage = 0; |
| if (m_reader) delete(m_reader); |
| m_reader = 0; |
| |
| m_writeAssistant = 0; |
| m_writeObject.reset(); |
| m_writeImage = 0; |
| if (m_writer) delete(m_writer); |
| m_writer = 0; |
| } |
| |
| bool openRead(Mode mode) { |
| close(); |
| |
| if ( (mode >= ModeAssistant && !m_currentAssistant) |
| || (mode >= ModeAssistant && m_currentAssistantIndex < 0) |
| || (mode >= ModePoint && !m_currentPointName) ) return false; |
| |
| m_readImage = dynamic_cast<TMetaImage*>(getImage(false)); |
| if (m_readImage) { |
| m_reader = new TMetaImage::Reader(*m_readImage); |
| if (mode == ModeImage) return true; |
| |
| if ( m_currentAssistantIndex < (int)(*m_reader)->size() |
| && (**m_reader)[m_currentAssistantIndex] == m_currentAssistant ) |
| { |
| m_readObject = (**m_reader)[m_currentAssistantIndex]; |
| m_readAssistant = m_readObject->getHandler<TAssistantBase>(); |
| if (mode == ModeAssistant) return true; |
| |
| if (m_readAssistant->findPoint(m_currentPointName)) { |
| if (mode == ModePoint) return true; |
| } |
| } |
| } |
| |
| close(); |
| return false; |
| } |
| |
| void touch() { |
| if (m_writeAssistant && !m_currentAssistantChanged) { |
| m_currentAssistantBackup = m_writeAssistant->data(); |
| m_currentAssistantChanged = true; |
| } |
| } |
| |
| bool openWrite(Mode mode, bool touch = false) { |
| close(); |
| |
| if ( (mode >= ModeAssistant && !m_currentAssistant) |
| || (mode >= ModeAssistant && m_currentAssistantIndex < 0) |
| || (mode >= ModePoint && !m_currentPointName) ) return false; |
| |
| m_writeImage = dynamic_cast<TMetaImage*>(getImage(true)); |
| if (m_writeImage) { |
| m_writer = new TMetaImage::Writer(*m_writeImage); |
| if (mode == ModeImage) return true; |
| |
| if ( m_currentAssistantIndex < (int)(*m_writer)->size() |
| && (**m_writer)[m_currentAssistantIndex] == m_currentAssistant ) |
| { |
| m_writeObject = (**m_writer)[m_currentAssistantIndex]; |
| m_writeAssistant = m_writeObject->getHandler<TAssistantBase>(); |
| if ( (mode == ModeAssistant) |
| || (mode == ModePoint && m_writeAssistant->findPoint(m_currentPointName)) ) |
| { |
| if (touch) this->touch(); |
| return true; |
| } |
| } |
| } |
| |
| close(); |
| return false; |
| } |
| |
| |
| |
| |
| struct Closer { |
| struct Args { |
| EditAssistantsTool *owner; |
| Args(EditAssistantsTool &owner): owner(&owner) { } |
| operator bool() const |
| { return owner && (owner->m_reader || owner->m_writer); } |
| void close() |
| { if (owner) owner->close(); } |
| }; |
| Closer(const Args &args): args(args) { } |
| ~Closer() { args.close(); } |
| operator bool() const { return args; } |
| private: |
| Args args; |
| }; |
| |
| Closer::Args read(Mode mode) |
| { openRead(mode); return Closer::Args(*this); } |
| Closer::Args write(Mode mode, bool touch = false) |
| { openWrite(mode, touch); return Closer::Args(*this); } |
| |
| void updateOptionsBox() |
| { getApplication()->getCurrentTool()->notifyToolOptionsBoxChanged(); } |
| |
| void resetCurrentPoint(bool updateOptionsBox = true, bool updateHistory = true) { |
| close(); |
| m_currentImage.reset(); |
| m_currentAssistant.reset(); |
| m_currentAssistantCreated = false; |
| m_currentAssistantChanged = false; |
| m_currentAssistantIndex = -1; |
| m_currentPointName.reset(); |
| m_currentPointOffset = TPointD(); |
| m_currentAssistantBackup.reset(); |
| |
| |
| if (Closer closer = read(ModeImage)) { |
| for(TMetaObjectListCW::iterator i = (*m_reader)->begin(); i != (*m_reader)->end(); ++i) |
| if (*i) |
| if (const TAssistantBase *assistant = (*i)->getHandler<TAssistantBase>()) |
| assistant->deselectAll(); |
| if (updateHistory) putHistory(m_readImage, -1); |
| } |
| |
| if (updateOptionsBox) this->updateOptionsBox(); |
| } |
| |
| bool chooseAssistant(int index) { |
| resetCurrentPoint(false); |
| if (index >= 0) |
| if (Closer closer = read(ModeImage)) { |
| m_currentImage.set(m_readImage); |
| if (index < (*m_reader)->size()) |
| if (const TMetaObjectPC &obj = (**m_reader)[index]) |
| if (const TAssistantBase *assistant = obj->getHandler<TAssistantBase>()) { |
| assistant->deselectAll(); |
| m_currentAssistant.set(obj); |
| m_currentAssistantIndex = index; |
| m_currentPointName = assistant->getBasePoint().name; |
| assistant->selectAll(); |
| } |
| putHistory(m_readImage, m_currentAssistantIndex); |
| } |
| this->updateOptionsBox(); |
| return m_currentAssistantIndex >= 0; |
| } |
| |
| bool findCurrentPoint(const TPointD &position, double pixelSize = 1, bool updateOptionsBox = true) { |
| resetCurrentPoint(false); |
| if (Closer closer = read(ModeImage)) { |
| m_currentImage.set(m_readImage); |
| for(TMetaObjectListCW::iterator i = (*m_reader)->begin(); i != (*m_reader)->end(); ++i) { |
| if (!*i) continue; |
| |
| const TAssistantBase *assistant = (*i)->getHandler<TAssistantBase>(); |
| if (!assistant) continue; |
| |
| assistant->deselectAll(); |
| |
| |
| |
| const TAssistantPointOrder &points = assistant->pointsOrder(); |
| for( TAssistantPointOrder::const_reverse_iterator j = points.rbegin(); |
| j != points.rend() && m_currentAssistantIndex < 0; |
| ++j ) |
| { |
| const TAssistantPoint &p = **j; |
| TPointD offset = p.position - position; |
| if (p.visible && norm2(offset) <= p.radius*p.radius*pixelSize*pixelSize) { |
| m_currentAssistant.set(*i); |
| m_currentAssistantIndex = i - (*m_reader)->begin(); |
| m_currentPointName = p.name; |
| m_currentPointOffset = offset; |
| assistant->selectAll(); |
| } |
| } |
| } |
| putHistory(m_readImage, m_currentAssistantIndex); |
| } |
| |
| if (updateOptionsBox) this->updateOptionsBox(); |
| return m_currentAssistantIndex >= 0; |
| } |
| |
| bool apply() { |
| bool success = false; |
| if (m_currentAssistantChanged || m_currentAssistantCreated) { |
| if (Closer closer = write(ModeAssistant)) { |
| m_writeAssistant->fixData(); |
| TUndoManager::manager()->add(new EditAssistantsUndo( |
| getApplication()->getCurrentLevel()->getLevel()->getSimpleLevel(), |
| getCurrentFid(), |
| m_isFrameCreated, |
| m_isLevelCreated, |
| m_currentAssistantCreated, |
| false, |
| m_currentAssistantIndex, |
| m_writeObject, |
| m_currentAssistantBackup )); |
| m_currentAssistantCreated = false; |
| m_currentAssistantChanged = false; |
| m_isFrameCreated = false; |
| m_isLevelCreated = false; |
| success = true; |
| } |
| } |
| |
| if (success) { |
| notifyImageChanged(); |
| getApplication()->getCurrentTool()->notifyToolChanged(); |
| TTool::getApplication()->getCurrentSelection()->setSelection( getSelection() ); |
| getViewer()->GLInvalidateAll(); |
| } |
| |
| return success; |
| } |
| |
| int readReplicatorIndex(TMetaImage::Reader &reader) { |
| int cnt = (int)reader->size(); |
| int index = 0; |
| for(int i = 0; i < cnt; ++i) { |
| if (const TMetaObjectPC &obj = (*reader)[i]) |
| if (obj->getHandler<TReplicator>()) { |
| ++index; |
| if (m_currentAssistantIndex == i) |
| return index; |
| } |
| } |
| return 0; |
| } |
| |
| void writeReplicatorIndex(int index) { |
| apply(); |
| |
| int wantIndex = index; |
| int oldPos = -1; |
| int newPos = -1; |
| bool changed = false; |
| |
| if (Closer closer = write(ModeAssistant)) { |
| if (index < 1) |
| index = 1; |
| |
| int idx = 0; |
| int lastPos = -1; |
| |
| TMetaObjectList &list = **m_writer; |
| |
| int cnt = (int)list.size(); |
| for(int i = 0; i < cnt; ++i) { |
| if (list[i] && list[i]->getHandler<TReplicator>()) { |
| ++idx; |
| if (m_currentAssistantIndex == i) oldPos = i; |
| if (idx == index) newPos = i; |
| lastPos = i; |
| } |
| } |
| |
| if (oldPos >= 0 && lastPos >= 0) { |
| assert(idx); |
| if (newPos < 0) |
| { index = idx; newPos = lastPos; } |
| if (oldPos != newPos) { |
| TMetaObjectP obj = list[oldPos]; |
| list.erase(list.begin() + oldPos); |
| list.insert(list.begin() + newPos, obj); |
| |
| TUndoManager::manager()->add(new EditAssistantsReorderUndo( |
| getApplication()->getCurrentLevel()->getLevel()->getSimpleLevel(), |
| getCurrentFid(), |
| oldPos, |
| newPos )); |
| |
| changed = true; |
| } |
| } |
| } |
| |
| if (changed) { |
| m_currentAssistantIndex = newPos; |
| invalidate(); |
| } |
| |
| if (wantIndex != index) |
| this->updateOptionsBox(); |
| } |
| |
| public: |
| void deselect() |
| { resetCurrentPoint(true, false); } |
| |
| bool isSelected() |
| { return read(ModeAssistant); } |
| |
| bool removeSelected() { |
| apply(); |
| bool success = false; |
| if (Closer closer = write(ModeAssistant, true)) { |
| (*m_writer)->erase((*m_writer)->begin() + m_currentAssistantIndex); |
| TUndoManager::manager()->add(new EditAssistantsUndo( |
| getApplication()->getCurrentLevel()->getLevel()->getSimpleLevel(), |
| getCurrentFid(), |
| false, |
| false, |
| false, |
| true, |
| m_currentAssistantIndex, m_writeObject, m_writeObject->data())); |
| success = true; |
| } |
| |
| if (success) notifyImageChanged(); |
| |
| resetCurrentPoint(); |
| getApplication()->getCurrentTool()->notifyToolChanged(); |
| TTool::getApplication()->getCurrentSelection()->setSelection( getSelection() ); |
| getViewer()->GLInvalidateAll(); |
| return success; |
| } |
| |
| bool preLeftButtonDown() override { |
| if (m_assistantType.getIndex() != 0) touchImage(); |
| TTool::getApplication()->getCurrentSelection()->setSelection( getSelection() ); |
| return true; |
| } |
| |
| void leftButtonDown(const TPointD &position, const TMouseEvent &event) override { |
| apply(); |
| m_dragging = true; |
| m_dragAllPoints = false; |
| if (m_newAssisnantType) { |
| |
| resetCurrentPoint(false); |
| if (Closer closer = write(ModeImage)) { |
| TMetaObjectP object(new TMetaObject(m_newAssisnantType)); |
| if (TAssistantBase *assistant = object->getHandler<TAssistantBase>()) { |
| assistant->setDefaults(); |
| assistant->move(position); |
| assistant->selectAll(); |
| m_currentImage.set(m_writeImage); |
| m_dragAllPoints = true; |
| m_currentAssistantCreated = true; |
| m_currentAssistantChanged = true; |
| m_currentAssistantIndex = (int)(*m_writer)->size(); |
| m_currentAssistant = object; |
| m_currentPointName = assistant->getBasePoint().name; |
| m_currentPointOffset = TPointD(); |
| m_currentAssistantBackup = assistant->data(); |
| (*m_writer)->push_back(object); |
| } |
| } |
| updateOptionsBox(); |
| m_newAssisnantType.reset(); |
| } else { |
| findCurrentPoint(position, getViewer()->getPixelSize()); |
| if (event.isShiftPressed()) |
| if (Closer closer = read(ModePoint)) { |
| m_currentPointName = m_readAssistant->getBasePoint().name; |
| m_currentPointOffset = m_readAssistant->getBasePoint().position - position; |
| m_dragAllPoints = true; |
| } |
| } |
| |
| m_currentPosition = position; |
| getViewer()->GLInvalidateAll(); |
| } |
| |
| void leftButtonDrag(const TPointD &position, const TMouseEvent&) override { |
| if (m_dragAllPoints) { |
| if (Closer closer = write(ModeAssistant)) |
| if (m_writeAssistant->move(position + m_currentPointOffset)) |
| touch(); |
| } else { |
| if (Closer closer = write(ModePoint)) |
| if (m_writeAssistant->movePoint(m_currentPointName, position + m_currentPointOffset)) |
| touch(); |
| } |
| m_currentPosition = position; |
| getViewer()->GLInvalidateAll(); |
| } |
| |
| void leftButtonUp(const TPointD &position, const TMouseEvent&) override { |
| if (m_dragAllPoints) { |
| if (Closer closer = write(ModeAssistant)) |
| if (m_writeAssistant->move(position + m_currentPointOffset)) |
| touch(); |
| } else { |
| if (Closer closer = write(ModePoint)) |
| if (m_writeAssistant->movePoint(m_currentPointName, position + m_currentPointOffset)) |
| touch(); |
| } |
| |
| apply(); |
| m_assistantType.setIndex(0); |
| getApplication()->getCurrentTool()->notifyToolChanged(); |
| TTool::getApplication()->getCurrentSelection()->setSelection( getSelection() ); |
| m_currentPosition = position; |
| getViewer()->GLInvalidateAll(); |
| m_dragAllPoints = false; |
| m_dragging = false; |
| } |
| |
| void mouseMove(const TPointD &position, const TMouseEvent&) override { |
| m_currentPosition = position; |
| m_currentPointOffset = TPointD(); |
| getViewer()->GLInvalidateAll(); |
| } |
| |
| void draw() override { |
| m_currentGuidelines.clear(); |
| TPointD position = m_currentPosition + m_currentPointOffset; |
| |
| |
| int index = 0; |
| if (Closer closer = read(ModeImage)) |
| for(TMetaObjectListCW::iterator i = (*m_reader)->begin(); i != (*m_reader)->end(); ++i) |
| if (*i) |
| if (const TAssistantBase *base = (*i)->getHandler<TAssistantBase>()) |
| { |
| if (dynamic_cast<const TReplicator*>(base)) { |
| ++index; |
| base->drawEdit(getViewer(), index); |
| } else { |
| base->drawEdit(getViewer()); |
| } |
| |
| if (const TAssistant *assistant = dynamic_cast<const TAssistant*>(base)) |
| assistant->getGuidelines( |
| position, |
| TAffine(), |
| m_currentGuidelines ); |
| } |
| |
| TImage *img = getImage(false); |
| |
| |
| TAssistant::scanAssistants( |
| this, |
| &position, 1, |
| &m_currentGuidelines, |
| true, |
| false, |
| false, |
| true, |
| img ); |
| |
| |
| TReplicator::scanReplicators( |
| this, |
| nullptr, |
| nullptr, |
| true, |
| false, |
| false, |
| false, |
| img ); |
| |
| |
| m_replicatorPoints.clear(); |
| m_replicatorPoints.push_back(position); |
| TReplicator::scanReplicators( |
| this, |
| &m_replicatorPoints, |
| nullptr, |
| false, |
| false, |
| false, |
| true, |
| nullptr ); |
| } |
| }; |
| |
| |
| |
| EditAssistantsTool editAssistantsTool; |