diff --git a/toonz/sources/include/tools/assistant.h b/toonz/sources/include/tools/assistant.h index 3ec9c7f..448f53f 100644 --- a/toonz/sources/include/tools/assistant.h +++ b/toonz/sources/include/tools/assistant.h @@ -46,7 +46,7 @@ class TGuideline; typedef TSmartPointerT TGuidelineP; typedef std::vector TGuidelineList; -typedef std::vector TAssistantPointList; +typedef std::map TAssistantPointMap; //=================================================================== @@ -97,16 +97,19 @@ public: enum Type { Circle, CircleFill, - CircleCross + CircleCross, + CircleGrid }; + const TStringId name; Type type; TPointD position; - mutable bool selected; double radius; + bool visible; + + mutable bool selected; - explicit TAssistantPoint(Type type = Circle, const TPointD &position = TPointD()); - TAssistantPoint(Type type, const TPointD &position, double radius); + explicit TAssistantPoint(const TStringId &name); }; @@ -189,26 +192,29 @@ protected: const TStringId m_idY; const TStringId m_idMagnetism; - TAssistantPointList m_points; + TAssistantPointMap m_points; + TAssistantPoint* m_basePoint; mutable TPropertyGroup m_properties; public: TAssistant(TMetaObject &object); - static const TPointD& blank(); - static QString getLocalName() { return QString(); } - inline const TAssistantPointList& points() const + inline const TAssistantPointMap& points() const { return m_points; } - inline const int pointsCount() const - { return (int)m_points.size(); } + + inline const TAssistantPoint* findPoint(const TStringId &name) const { + TAssistantPointMap::const_iterator i = points().find(name); + return i == points().end() ? 0 : &i->second; + } void fixPoints(); - void movePoint(int index, const TPointD &position); - void setPointSelection(int index, bool selected) const; + void movePoint(const TStringId &name, const TPointD &position); + void setPointSelection(const TStringId &name, bool selected) const; + void setAllPointsSelection(bool selected) const; bool getEnabled() const { return data()[m_idEnabled].getBool(); } @@ -220,21 +226,51 @@ public: void setMagnetism(double x) { if (getMagnetism() != x) data()[m_idMagnetism].setDouble(x); } - inline void selectPoint(int index) const - { setPointSelection(index, true); } - inline void deselectPoint(int index) const - { setPointSelection(index, false); } + inline void selectPoint(const TStringId &name) const + { setPointSelection(name, true); } + inline void deselectPoint(const TStringId &name) const + { setPointSelection(name, false); } inline void selectAll() const - { for(int i = 0; i < pointsCount(); ++i) setPointSelection(i, true); } + { setAllPointsSelection(true); } inline void deselectAll() const - { for(int i = 0; i < pointsCount(); ++i) setPointSelection(i, false); } + { setAllPointsSelection(false); } TPropertyGroup& getProperties() const { return m_properties; } void propertyChanged(const TStringId &name) { LockEvents lock(*this); onPropertyChanged(name); } + const TAssistantPoint& getBasePoint() const; + protected: + TAssistantPoint& addPoint( + const TStringId &name, + TAssistantPoint::Type type, + const TPointD &position, + bool visible, + double radius ); + + TAssistantPoint& addPoint( + const TStringId &name, + TAssistantPoint::Type type = TAssistantPoint::Circle, + const TPointD &position = TPointD(), + bool visible = true ); + + inline TAssistantPoint& addPoint( + const std::string &name, + TAssistantPoint::Type type, + const TPointD &position, + bool visible, + double radius ) + { return addPoint(TStringId(name), type, position, visible, radius); } + + inline TAssistantPoint& addPoint( + const std::string &name, + TAssistantPoint::Type type = TAssistantPoint::Circle, + const TPointD &position = TPointD(), + bool visible = true ) + { return addPoint(TStringId(name), type, position, visible); } + //! usually called when meta-object created void onSetDefaults() override; //! called when part of variant data changed @@ -244,7 +280,7 @@ protected: //! fix positions of all points (as like as all points moved) virtual void onFixPoints(); //! try to move point - virtual void onMovePoint(int index, const TPointD &position); + virtual void onMovePoint(TAssistantPoint &point, const TPointD &position); //! save object data to variant virtual void onFixData(); //! load all properties from variant diff --git a/toonz/sources/tnztools/assistant.cpp b/toonz/sources/tnztools/assistant.cpp index b4f669f..a7a4451 100644 --- a/toonz/sources/tnztools/assistant.cpp +++ b/toonz/sources/tnztools/assistant.cpp @@ -5,6 +5,7 @@ #include #include +#include //************************************************************************ @@ -105,25 +106,12 @@ TGuideline::findBest(const TGuidelineList &guidelines, const TTrack &track, cons // TAssistantPoint implementation //************************************************************************ -TAssistantPoint::TAssistantPoint( - Type type, - const TPointD &position -): - type(type), +TAssistantPoint::TAssistantPoint(const TStringId &name): + name(name), + type(Circle), position(position), radius(10.0), - selected() { } - -//--------------------------------------------------------------------------------------------------- - -TAssistantPoint::TAssistantPoint( - Type type, - const TPointD &position, - double radius -): - type(type), - position(position), - radius(radius), + visible(true), selected() { } @@ -146,7 +134,8 @@ TAssistant::TAssistant(TMetaObject &object): m_idPoints("points"), m_idX("x"), m_idY("y"), - m_idMagnetism("magnetism") + m_idMagnetism("magnetism"), + m_basePoint() { addProperty( new TBoolProperty(m_idEnabled.str(), getEnabled()) ); addProperty( new TDoubleProperty(m_idMagnetism.str(), 0.0, 1.0, getMagnetism()) ); @@ -154,6 +143,43 @@ TAssistant::TAssistant(TMetaObject &object): //--------------------------------------------------------------------------------------------------- +TAssistantPoint& +TAssistant::addPoint( + const TStringId &name, + TAssistantPoint::Type type, + const TPointD &position, + bool visible, + double radius ) +{ + assert(!m_points.count(name)); + TAssistantPoint &p = m_points.insert( + TAssistantPointMap::value_type(name, TAssistantPoint(name)) ).first->second; + p.type = type; + p.position = position; + p.radius = radius; + p.visible = visible; + if (!m_basePoint) m_basePoint = &p; + return p; +} + +//--------------------------------------------------------------------------------------------------- + +TAssistantPoint& +TAssistant::addPoint( + const TStringId &name, + TAssistantPoint::Type type, + const TPointD &position, + bool visible ) + { return addPoint(name, type, position, visible, 10.0); } + +//--------------------------------------------------------------------------------------------------- + +const TAssistantPoint& +TAssistant::getBasePoint() const + { assert(m_basePoint); return *m_basePoint; } + +//--------------------------------------------------------------------------------------------------- + void TAssistant::addProperty(TProperty *p) { m_properties.add(p); } @@ -182,30 +208,33 @@ TAssistant::onSetDefaults() { //--------------------------------------------------------------------------------------------------- -const TPointD& -TAssistant::blank() { - static TPointD point; - return point; -} +void +TAssistant::fixPoints() + { onFixPoints(); } //--------------------------------------------------------------------------------------------------- void -TAssistant::fixPoints() - { onFixPoints(); } +TAssistant::movePoint(const TStringId &name, const TPointD &position) { + TAssistantPointMap::iterator i = m_points.find(name); + if (i != m_points.end()) + onMovePoint(i->second, position); +} //--------------------------------------------------------------------------------------------------- void -TAssistant::movePoint(int index, const TPointD &position) - { if (index >= 0 && index < (int)m_points.size()) onMovePoint(index, position); } +TAssistant::setPointSelection(const TStringId &name, bool selected) const { + if (const TAssistantPoint *p = findPoint(name)) + p->selected = selected; +} //--------------------------------------------------------------------------------------------------- void -TAssistant::setPointSelection(int index, bool selected) const { - if (index >= 0 && index < pointsCount()) - m_points[index].selected = selected; +TAssistant::setAllPointsSelection(bool selected) const { + for(TAssistantPointMap::const_iterator i = points().begin(); i != points().end(); ++i) + i->second.selected = selected; } //--------------------------------------------------------------------------------------------------- @@ -218,12 +247,12 @@ TAssistant::onDataChanged(const TVariant &value) { if (&value == &data() || &value == &pointsData) onAllDataChanged(); else - if (pointsData.getChildPathEntry(value, entry) && entry.isIndex()) { + if (pointsData.getChildPathEntry(value, entry) && entry.isField()) { const TVariant& pointData = pointsData[entry]; TPointD position = TPointD( pointData[m_idX].getDouble(), pointData[m_idY].getDouble() ); - movePoint(entry.index(), position); + movePoint(entry.field(), position); } else if (data().getChildPathEntry(value, entry) && entry.isField()) { updateProperty(entry.field(), data()[entry.field()]); @@ -235,9 +264,9 @@ TAssistant::onDataChanged(const TVariant &value) { void TAssistant::onAllDataChanged() { const TVariant& pointsData = data()[m_idPoints]; - for(int i = 0; i < pointsCount(); ++i) { - const TVariant& pointData = pointsData[i]; - m_points[i].position = TPointD( + for(TAssistantPointMap::iterator i = m_points.begin(); i != m_points.end(); ++i) { + const TVariant& pointData = pointsData[i->first]; + i->second.position = TPointD( pointData[m_idX].getDouble(), pointData[m_idY].getDouble() ); } @@ -254,18 +283,18 @@ TAssistant::onFixPoints() //--------------------------------------------------------------------------------------------------- void -TAssistant::onMovePoint(int index, const TPointD &position) - { m_points[index].position = position; } +TAssistant::onMovePoint(TAssistantPoint &point, const TPointD &position) + { point.position = position; } //--------------------------------------------------------------------------------------------------- void TAssistant::onFixData() { TVariant& pointsData = data()[m_idPoints]; - for(int i = 0; i < pointsCount(); ++i) { - TVariant& pointData = pointsData[i]; - pointData[m_idX].setDouble( m_points[i].position.x ); - pointData[m_idY].setDouble( m_points[i].position.y ); + for(TAssistantPointMap::const_iterator i = points().begin(); i != points().end(); ++i) { + TVariant& pointData = pointsData[i->first]; + pointData[m_idX].setDouble( i->second.position.x ); + pointData[m_idY].setDouble( i->second.position.y ); } setMagnetism( std::max(0.0, std::min(1.0, getMagnetism())) ); } @@ -356,6 +385,8 @@ TAssistant::drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize, void TAssistant::drawPoint(const TAssistantPoint &point, double pixelSize) const { + if (!point.visible) return; + double radius = point.radius; double crossSize = 1.2*radius; @@ -422,8 +453,8 @@ TAssistant::drawEdit(TToolViewer *viewer) const { // paint all points draw(viewer); double pixelSize = sqrt(tglGetPixelSize2()); - for(int i = 0; i < pointsCount(); ++i) - drawPoint(m_points[i], pixelSize); + for(TAssistantPointMap::const_iterator i = points().begin(); i != points().end(); ++i) + drawPoint(i->second, pixelSize); } //--------------------------------------------------------------------------------------------------- diff --git a/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp b/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp index 0c4a3f9..0e7887b 100644 --- a/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp +++ b/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp @@ -15,13 +15,14 @@ class DVAPI TAssistantVanishingPoint final : public TAssistant { Q_DECLARE_TR_FUNCTIONS(TAssistantVanishingPoint) +protected: + TAssistantPoint &m_pointCenter; + public: TAssistantVanishingPoint(TMetaObject &object): - TAssistant(object) - { - m_points.push_back(TAssistantPoint( - TAssistantPoint::CircleCross )); - } + TAssistant(object), + m_pointCenter( addPoint("center", TAssistantPoint::CircleCross) ) + { } static QString getLocalName() { return tr("Vanishing Point"); } @@ -35,13 +36,13 @@ public: new TGuidelineInfiniteLine( getEnabled(), getMagnetism(), - toTool*m_points.front().position, + toTool * m_pointCenter.position, position ))); } void draw(TToolViewer *viewer, bool enabled) const override { double pixelSize = sqrt(tglGetPixelSize2()); - const TPointD &p = m_points.front().position; + const TPointD &p = m_pointCenter.position; TPointD dx(20.0*pixelSize, 0.0); TPointD dy(0.0, 10.0*pixelSize); drawSegment(p-dx-dy, p+dx+dy, pixelSize, enabled); diff --git a/toonz/sources/tnztools/editassistantstool.cpp b/toonz/sources/tnztools/editassistantstool.cpp index d89ac37..f694613 100644 --- a/toonz/sources/tnztools/editassistantstool.cpp +++ b/toonz/sources/tnztools/editassistantstool.cpp @@ -33,6 +33,7 @@ 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; @@ -46,12 +47,14 @@ public: 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()), @@ -64,24 +67,23 @@ public: { return QString("Edit Assistants Tool"); } void process(bool remove, const TVariant &data) const { - if (TMetaImage *metaImage = dynamic_cast(m_level->getFrame(m_frameId, true).getPointer())) - { - { // wrap writer - 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->push_back(m_metaObject); - m_metaObject->data() = data; - if (m_metaObject->handler()) - m_metaObject->handler()->fixData(); + if (TMetaImage *metaImage = dynamic_cast(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(); } } } @@ -126,7 +128,7 @@ protected: bool m_currentAssistantChanged; int m_currentAssistantIndex; TVariant m_currentAssistantBackup; - int m_currentPointIndex; + TStringId m_currentPointName; TPointD m_currentPointOffset; TPointD m_currentPosition; TGuidelineList m_currentGuidelines; @@ -149,7 +151,6 @@ public: m_currentAssistantCreated(), m_currentAssistantChanged(), m_currentAssistantIndex(-1), - m_currentPointIndex(-1), m_reader(), m_readImage(), m_readAssistant(), @@ -246,7 +247,7 @@ protected: if ( (mode >= ModeAssistant && !m_currentAssistant) || (mode >= ModeAssistant && m_currentAssistantIndex < 0) - || (mode >= ModePoint && m_currentPointIndex < 0) ) return false; + || (mode >= ModePoint && !m_currentPointName) ) return false; m_readImage = dynamic_cast(getImage(true)); if (m_readImage) { @@ -260,7 +261,7 @@ protected: m_readAssistant = m_readObject->getHandler(); if (mode == ModeAssistant) return true; - if (m_currentPointIndex < m_readAssistant->pointsCount()) { + if (m_readAssistant->findPoint(m_currentPointName)) { if (mode == ModePoint) return true; } } @@ -282,7 +283,7 @@ protected: if ( (mode >= ModeAssistant && !m_currentAssistant) || (mode >= ModeAssistant && m_currentAssistantIndex < 0) - || (mode >= ModePoint && m_currentPointIndex < 0) ) return false; + || (mode >= ModePoint && !m_currentPointName) ) return false; m_writeImage = dynamic_cast(getImage(true)); if (m_writeImage) { @@ -295,7 +296,7 @@ protected: m_writeObject = (**m_writer)[m_currentAssistantIndex]; m_writeAssistant = m_writeObject->getHandler(); if ( (mode == ModeAssistant) - || (mode == ModePoint && m_currentPointIndex < m_writeAssistant->pointsCount()) ) + || (mode == ModePoint && m_writeAssistant->findPoint(m_currentPointName)) ) { if (touch) this->touch(); return true; @@ -340,7 +341,7 @@ protected: m_currentAssistantCreated = false; m_currentAssistantChanged = false; m_currentAssistantIndex = -1; - m_currentPointIndex = -1; + m_currentPointName.reset(); m_currentPointOffset = TPointD(); m_currentAssistantBackup.reset(); if (updateOptionsBox) this->updateOptionsBox(); @@ -356,13 +357,14 @@ protected: if (!assistant) continue; assistant->deselectAll(); - for(int j = 0; j < assistant->pointsCount() && m_currentAssistantIndex < 0; ++j) { - const TAssistantPoint &p = assistant->points()[j]; + const TAssistantPointMap &points = assistant->points(); + for(TAssistantPointMap::const_iterator j = points.begin(); j != points.end() && m_currentAssistantIndex < 0; ++j) { + const TAssistantPoint &p = j->second; TPointD offset = p.position - position; - if (norm2(offset) <= p.radius*p.radius*pixelSize*pixelSize) { + if (p.visible && norm2(offset) <= p.radius*p.radius*pixelSize*pixelSize) { m_currentAssistant.set(*i); m_currentAssistantIndex = i - (*m_reader)->begin(); - m_currentPointIndex = j; + m_currentPointName = j->first; m_currentPointOffset = offset; assistant->selectAll(); } @@ -386,6 +388,7 @@ protected: m_isLevelCreated, m_currentAssistantCreated, false, + m_currentAssistantIndex, m_writeObject, m_currentAssistantBackup )); m_currentAssistantCreated = false; @@ -420,17 +423,15 @@ public: if (Closer closer = write(ModeImage)) { TMetaObjectP object(new TMetaObject(m_newAssisnantType)); if (TAssistant *assistant = object->getHandler()) { - if (assistant->pointsCount()) { - assistant->setDefaults(); - assistant->movePoint(0, position); - m_currentAssistantCreated = true; - m_currentAssistantChanged = true; - m_currentAssistantIndex = (int)(*m_writer)->size(); - m_currentAssistant = object; - m_currentPointIndex = 0; - m_currentPointOffset = TPointD(); - m_currentAssistantBackup = assistant->data(); - } + assistant->setDefaults(); + assistant->movePoint(assistant->getBasePoint().name, position); + 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); } } @@ -446,7 +447,7 @@ public: void leftButtonDrag(const TPointD &position, const TMouseEvent&) override { if (Closer closer = write(ModePoint, true)) m_writeAssistant->movePoint( - m_currentPointIndex, + m_currentPointName, position + m_currentPointOffset); m_currentPosition = position; getViewer()->GLInvalidateAll(); @@ -455,7 +456,7 @@ public: void leftButtonUp(const TPointD &position, const TMouseEvent&) override { if (Closer closer = write(ModePoint, true)) m_writeAssistant->movePoint( - m_currentPointIndex, + m_currentPointName, position + m_currentPointOffset); apply(); @@ -481,6 +482,7 @@ public: false, // levelCreated false, // objectCreated true, // objectRemoved + m_currentAssistantIndex, m_writeObject, m_writeObject->data() )); success = true;