diff --git a/toonz/sources/common/tvrender/tcolorstyles.cpp b/toonz/sources/common/tvrender/tcolorstyles.cpp index 3b18ce5..a67f8f1 100644 --- a/toonz/sources/common/tvrender/tcolorstyles.cpp +++ b/toonz/sources/common/tvrender/tcolorstyles.cpp @@ -50,7 +50,8 @@ TColorStyle::TColorStyle() , m_enabled(true) , m_icon(0) , m_validIcon(false) - , m_isEditedFromOriginal(false) {} + , m_isEditedFromOriginal(false) + , m_pickedPosition() {} //------------------------------------------------------------------- @@ -66,7 +67,8 @@ TColorStyle::TColorStyle(const TColorStyle &other) , m_flags(other.m_flags) , m_enabled(other.m_enabled) , m_validIcon(false) - , m_isEditedFromOriginal(other.m_isEditedFromOriginal) {} + , m_isEditedFromOriginal(other.m_isEditedFromOriginal) + , m_pickedPosition(other.m_pickedPosition) {} //------------------------------------------------------------------- @@ -79,6 +81,7 @@ TColorStyle &TColorStyle::operator=(const TColorStyle &other) { m_enabled = other.m_enabled; m_validIcon = false; m_isEditedFromOriginal = other.m_isEditedFromOriginal; + m_pickedPosition = other.m_pickedPosition; return *this; } @@ -100,6 +103,7 @@ bool TColorStyle::operator==(const TColorStyle &cs) const { if (m_originalName != cs.getOriginalName()) return false; if (m_globalName != cs.getGlobalName()) return false; if (m_isEditedFromOriginal != cs.getIsEditedFlag()) return false; + if (m_pickedPosition != cs.getPickedPosition()) return false; for (int p = 0; p < colorParamCount; ++p) if (getColorParamValue(p) != cs.getColorParamValue(p)) return false; diff --git a/toonz/sources/common/tvrender/tpalette.cpp b/toonz/sources/common/tvrender/tpalette.cpp index e301908..3f7f9c0 100644 --- a/toonz/sources/common/tvrender/tpalette.cpp +++ b/toonz/sources/common/tvrender/tpalette.cpp @@ -15,6 +15,7 @@ #include "tpalette.h" #include +#include PERSIST_IDENTIFIER(TPalette, "palette") @@ -30,6 +31,21 @@ namespace { const int maxStyleIndex = 32765; +const std::string pointToString(const TPoint &point) { + return std::to_string(point.x) + "," + std::to_string(point.y); +} + +// splitting string with ',' +const TPoint stringToPoint(const std::string &string) { + std::string buffer; + std::stringstream ss(string); + std::getline(ss, buffer, ','); // getting the first part of string + int x = std::stoi(buffer); + std::getline(ss, buffer); // getting the second part of string + int y = std::stoi(buffer); + return TPoint(x, y); +} + } // namespace //=================================================================== @@ -563,10 +579,17 @@ void TPalette::saveData(TOStream &os) { os.openChild("styles"); { for (int i = 0; i < getStyleCount(); ++i) { - os.openChild("style"); + TColorStyleP style = m_styles[i].second; + if (style->getPickedPosition() == TPoint()) + os.openChild("style"); + else { + std::map attr; + attr["pickedpos"] = pointToString(style->getPickedPosition()); + os.openChild("style", attr); + } { StyleWriter w(os, i); - m_styles[i].second->save(w); + style->save(w); } os.closeChild(); } @@ -680,6 +703,10 @@ void TPalette::loadData(TIStream &is) { StyleReader r(is, version); TColorStyle *cs = TColorStyle::load(r); + std::string pickedPosStr; + if (is.getTagParam("pickedpos", pickedPosStr)) + cs->setPickedPosition(stringToPoint(pickedPosStr)); + addStyle(cs); } diff --git a/toonz/sources/include/tcolorstyles.h b/toonz/sources/include/tcolorstyles.h index 1b999e7..2aecdad 100644 --- a/toonz/sources/include/tcolorstyles.h +++ b/toonz/sources/include/tcolorstyles.h @@ -118,6 +118,9 @@ private: // This flag will be set when the //! style is edited from the original one. + TPoint m_pickedPosition; // picked position from color model by using style + // picker tool with "organize palette" option. + protected: TRaster32P m_icon; //!< Icon shown on TPalette viewers. bool m_validIcon; //!< Icon's validity status. @@ -212,6 +215,9 @@ The \a global name contains information about palette id. m_flags = flags; } //!< Returns color attributes. + void setPickedPosition(const TPoint &pos) { m_pickedPosition = pos; } + TPoint getPickedPosition() const { return m_pickedPosition; } + // Color-related functions /*! \detail diff --git a/toonz/sources/include/toonz/palettecmd.h b/toonz/sources/include/toonz/palettecmd.h index cc37f9d..da63518 100644 --- a/toonz/sources/include/toonz/palettecmd.h +++ b/toonz/sources/include/toonz/palettecmd.h @@ -89,7 +89,8 @@ DVAPI void renamePaletteStyle(TPaletteHandle *paletteHandle, const std::wstring &newName); /* called in ColorModelViewer::pick() - move selected style to the first page */ -DVAPI void organizePaletteStyle(TPaletteHandle *paletteHandle, int styleId); +DVAPI void organizePaletteStyle(TPaletteHandle *paletteHandle, int styleId, + const TPoint &point); } // namespace diff --git a/toonz/sources/tnztools/cursormanager.cpp b/toonz/sources/tnztools/cursormanager.cpp index 849ce80..323ba47 100644 --- a/toonz/sources/tnztools/cursormanager.cpp +++ b/toonz/sources/tnztools/cursormanager.cpp @@ -74,7 +74,8 @@ const struct { {ToolCursor::PickerCursorWhiteArea, "picker_style_white_area", 7, 22}, {ToolCursor::PickerCursorWhite, "picker_style_white", 7, 22}, {ToolCursor::PickerCursorOrganize, "picker_style_organize", 7, 22}, - {ToolCursor::PickerCursorWhiteOrganize, "picker_style_white_organize", 7, 22}, + {ToolCursor::PickerCursorWhiteOrganize, "picker_style_white_organize", 7, + 22}, {ToolCursor::PickerRGB, "picker_rgb", 7, 22}, {ToolCursor::PickerRGBWhite, "picker_rgb_white", 7, 22}, {ToolCursor::FillCursorF, "fill_f", 6, 23}, diff --git a/toonz/sources/tnztools/stylepickertool.cpp b/toonz/sources/tnztools/stylepickertool.cpp index 459cfec..4c21641 100644 --- a/toonz/sources/tnztools/stylepickertool.cpp +++ b/toonz/sources/tnztools/stylepickertool.cpp @@ -1,16 +1,16 @@ #include "stylepickertool.h" -//TnzTools includes +// TnzTools includes #include "tools/tool.h" #include "tools/cursors.h" #include "tools/stylepicker.h" #include "tools/toolhandle.h" -//TnzQt includes +// TnzQt includes #include "toonzqt/tselectionhandle.h" #include "toonzqt/styleselection.h" -//TnzLib includes +// TnzLib includes #include "toonz/txshsimplelevel.h" #include "toonz/txshlevelhandle.h" #include "toonz/tpalettehandle.h" @@ -43,7 +43,7 @@ StylePickerTool::StylePickerTool() : TTool("T_StylePicker") , m_currentStyleId(0) , m_colorType("Mode:") - , m_passivePick("Passive Pick", false) + , m_passivePick("Passive Pick", false) , m_organizePalette("Organize Palette", false) , m_paletteToBeOrganized(NULL) { m_prop.bind(m_colorType); @@ -60,13 +60,12 @@ StylePickerTool::StylePickerTool() m_organizePalette.setId("OrganizePalette"); } - void StylePickerTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) { m_oldStyleId = m_currentStyleId = getApplication()->getCurrentLevelStyleIndex(); pick(pos, e); } - + void StylePickerTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) { pick(pos, e); } @@ -104,12 +103,10 @@ void StylePickerTool::pick(const TPointD &pos, const TMouseEvent &e) { TVectorImageP picked_vi = pickedImage; TXshSimpleLevel *picked_level = pickedCell.getSimpleLevel(); if ((picked_ti || picked_vi) && picked_level) { - TPointD tmpMousePosition = - getColumnMatrix(superPickedColumnId).inv() * - getViewer()->winToWorld(e.m_pos); + TPointD tmpMousePosition = getColumnMatrix(superPickedColumnId).inv() * + getViewer()->winToWorld(e.m_pos); - TPointD tmpDpiScale = - getCurrentDpiScale(picked_level, getCurrentFid()); + TPointD tmpDpiScale = getCurrentDpiScale(picked_level, getCurrentFid()); tmpMousePosition.x /= tmpDpiScale.x; tmpMousePosition.y /= tmpDpiScale.y; @@ -155,9 +152,9 @@ void StylePickerTool::pick(const TPointD &pos, const TMouseEvent &e) { int subsampling = level->getImageSubsampling(getCurrentFid()); StylePicker picker(image); - int styleId = picker.pickStyleId( - TScale(1.0 / subsampling) * pos + TPointD(-0.5, -0.5), - getPixelSize() * getPixelSize(), modeValue); + int styleId = + picker.pickStyleId(TScale(1.0 / subsampling) * pos + TPointD(-0.5, -0.5), + getPixelSize() * getPixelSize(), modeValue); if (styleId < 0) return; @@ -216,28 +213,27 @@ void StylePickerTool::mouseMove(const TPointD &pos, const TMouseEvent &e) { int StylePickerTool::getCursorId() const { bool isBlackBG = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg; - + /* in case the "organize palette" option is active */ if (m_organizePalette.getValue()) return (isBlackBG) ? ToolCursor::PickerCursorWhiteOrganize - : ToolCursor::PickerCursorOrganize; + : ToolCursor::PickerCursorOrganize; if (m_colorType.getValue() == LINES) return (isBlackBG) ? ToolCursor::PickerCursorWhiteLine - : ToolCursor::PickerCursorLine; + : ToolCursor::PickerCursorLine; else if (m_colorType.getValue() == AREAS) return (isBlackBG) ? ToolCursor::PickerCursorWhiteArea - : ToolCursor::PickerCursorArea; + : ToolCursor::PickerCursorArea; else // line&areas return (isBlackBG) ? ToolCursor::PickerCursorWhite - : ToolCursor::PickerCursor; + : ToolCursor::PickerCursor; } bool StylePickerTool::onPropertyChanged(std::string propertyName) { - if (propertyName == m_organizePalette.getName()){ - + if (propertyName == m_organizePalette.getName()) { if (m_organizePalette.getValue()) { - if (!startOrganizePalette()){ + if (!startOrganizePalette()) { m_organizePalette.setValue(false); getApplication()->getCurrentTool()->notifyToolChanged(); return false; @@ -252,48 +248,50 @@ bool StylePickerTool::onPropertyChanged(std::string propertyName) { bool StylePickerTool::startOrganizePalette() { /* Check if the organizing operation is available */ - TXshLevel* level = getApplication()->getCurrentLevel()->getLevel(); + TXshLevel *level = getApplication()->getCurrentLevel()->getLevel(); if (!level) { DVGui::error(tr("No current level.")); return false; } - if ( level->getType() != PLI_XSHLEVEL && level->getType() != TZP_XSHLEVEL - && level->getType() != PLT_XSHLEVEL ) { + if (level->getType() != PLI_XSHLEVEL && level->getType() != TZP_XSHLEVEL && + level->getType() != PLT_XSHLEVEL) { DVGui::error(tr("Current level has no available palette.")); return false; } /* palette should have more than one page to organize */ - TPalette* pal = NULL; + TPalette *pal = NULL; if (level->getType() == PLT_XSHLEVEL) pal = level->getPaletteLevel()->getPalette(); else pal = level->getSimpleLevel()->getPalette(); - if (!pal || pal->getPageCount() < 2){ - DVGui::error(tr("Palette must have more than one palette to be organized.")); + if (!pal || pal->getPageCount() < 2) { + DVGui::error( + tr("Palette must have more than one palette to be organized.")); return false; } m_paletteToBeOrganized = pal; - + std::cout << "Start Organize Palette" << std::endl; return true; } /* - If the working palette is changed, then deactivate the "organize palette" toggle. + If the working palette is changed, then deactivate the "organize palette" + toggle. */ void StylePickerTool::onImageChanged() { std::cout << "StylePickerTool::onImageChanged" << std::endl; - if (!m_organizePalette.getValue() || !m_paletteToBeOrganized)return; + if (!m_organizePalette.getValue() || !m_paletteToBeOrganized) return; - TXshLevel* level = getApplication()->getCurrentLevel()->getLevel(); + TXshLevel *level = getApplication()->getCurrentLevel()->getLevel(); if (!level) { m_organizePalette.setValue(false); getApplication()->getCurrentTool()->notifyToolChanged(); return; } - TPalette* pal = NULL; + TPalette *pal = NULL; if (level->getType() == PLT_XSHLEVEL) pal = level->getPaletteLevel()->getPalette(); else if (level->getSimpleLevel()) { @@ -306,6 +304,4 @@ void StylePickerTool::onImageChanged() { } } - StylePickerTool stylePickerTool; - diff --git a/toonz/sources/tnztools/stylepickertool.h b/toonz/sources/tnztools/stylepickertool.h index 333ac0e..2a6982a 100644 --- a/toonz/sources/tnztools/stylepickertool.h +++ b/toonz/sources/tnztools/stylepickertool.h @@ -13,11 +13,12 @@ class StylePickerTool final : public TTool, public QObject { TEnumProperty m_colorType; TPropertyGroup m_prop; TBoolProperty m_passivePick; - + TBoolProperty m_organizePalette; - TPalette* m_paletteToBeOrganized; + TPalette *m_paletteToBeOrganized; bool startOrganizePalette(); + public: TPropertyGroup *getProperties(int targetType) override { return &m_prop; } @@ -34,20 +35,20 @@ public: void pick(const TPointD &pos, const TMouseEvent &e); void mouseMove(const TPointD &pos, const TMouseEvent &e) override; - + int getCursorId() const override; bool onPropertyChanged(std::string propertyName); bool isOrganizePaletteActive() { return m_organizePalette.getValue(); } - /* - This function is called when either frame/column/level/scene is switched or + /* + This function is called when either frame/column/level/scene is switched or either scene/level/object is changed (see tapp.cpp). - If the working palette is changed, then deactivate the "organize palette" toggle. + If the working palette is changed, then deactivate the "organize palette" + toggle. */ void onImageChanged() override; }; - #endif \ No newline at end of file diff --git a/toonz/sources/tnztools/tooloptions.cpp b/toonz/sources/tnztools/tooloptions.cpp index 04e0611..28ed771 100644 --- a/toonz/sources/tnztools/tooloptions.cpp +++ b/toonz/sources/tnztools/tooloptions.cpp @@ -2182,14 +2182,16 @@ StylePickerToolOptionsBox::StylePickerToolOptionsBox( m_layout->addWidget(m_currentStyleLabel, 0); m_layout->addStretch(1); - // retrieve the "organize palette" checkbox from the layout and insert + // retrieve the "organize palette" checkbox from the layout and insert // into rightmost of the tool option bar - ToolOptionCheckbox* organizePaletteCB = - dynamic_cast(m_controls.value("Organize Palette")); + ToolOptionCheckbox *organizePaletteCB = + dynamic_cast(m_controls.value("Organize Palette")); m_layout->removeWidget(organizePaletteCB); m_layout->addWidget(new ToolOptionsBarSeparator(this), 0); m_layout->addWidget(organizePaletteCB); - organizePaletteCB->setToolTip(tr("With this option being activated, the picked style will be\nmoved to the end of the first page of the palette.")); + organizePaletteCB->setToolTip( + tr("With this option being activated, the picked style will be\nmoved to " + "the end of the first page of the palette.")); if (m_realTimePickMode) { connect(m_realTimePickMode, SIGNAL(toggled(bool)), m_currentStyleLabel, diff --git a/toonz/sources/toonz/colormodelviewer.cpp b/toonz/sources/toonz/colormodelviewer.cpp index 474a3e0..6636000 100644 --- a/toonz/sources/toonz/colormodelviewer.cpp +++ b/toonz/sources/toonz/colormodelviewer.cpp @@ -307,15 +307,16 @@ void ColorModelViewer::pick(const QPoint &p) { if (styleSelection) styleSelection->selectNone(); } - /* + /* if the Style Picker tool is current and "organize palette" is activated, - then move the picked style to the first page of the palette. + then move the picked style to the first page of the palette. */ TTool *tool = TApp::instance()->getCurrentTool()->getTool(); - if (tool->getName() == "T_StylePicker"){ - StylePickerTool* spTool = dynamic_cast(tool); - if (spTool && spTool->isOrganizePaletteActive()){ - PaletteCmd::organizePaletteStyle(ph, styleIndex); + if (tool->getName() == "T_StylePicker") { + StylePickerTool *spTool = dynamic_cast(tool); + if (spTool && spTool->isOrganizePaletteActive()) { + TPoint point = picker.getRasterPoint(pos); + PaletteCmd::organizePaletteStyle(ph, styleIndex, point); } } @@ -371,7 +372,7 @@ void ColorModelViewer::showEvent(QShowEvent *e) { void ColorModelViewer::changePickType() { TTool *tool = TApp::instance()->getCurrentTool()->getTool(); if (tool->getName() == T_StylePicker) { - StylePickerTool* stylePickerTool = dynamic_cast(tool); + StylePickerTool *stylePickerTool = dynamic_cast(tool); if (stylePickerTool->isOrganizePaletteActive()) { setToolCursor(m_imageViewer, ToolCursor::PickerCursorOrganize); return; diff --git a/toonz/sources/toonzlib/convert2tlv.cpp b/toonz/sources/toonzlib/convert2tlv.cpp index 6663848..2fbed64 100644 --- a/toonz/sources/toonzlib/convert2tlv.cpp +++ b/toonz/sources/toonzlib/convert2tlv.cpp @@ -566,15 +566,16 @@ TPalette *Convert2Tlv::buildPalette() { page->addStyle(stylesToBeAddedToPage.at(s)); } - /* - If the palette path is empty, an initial palette with four colors are set in the palette here. - ( see Convert2Tlv::init() ) So here I make the latter three styles in the initial palette to set + /* + If the palette path is empty, an initial palette with four colors are set in + the palette here. + ( see Convert2Tlv::init() ) So here I make the latter three styles in the + initial palette to set "AutoPaint" options. */ if (m_palettePath.isEmpty()) { assert(m_palette->getStyleCount() >= 5); - for (int id = 2; id <= 4; id++) - m_palette->getStyle(id)->setFlags(1); + for (int id = 2; id <= 4; id++) m_palette->getStyle(id)->setFlags(1); } if (!m_appendDefaultPalette) return m_palette; @@ -821,14 +822,15 @@ bool Convert2Tlv::init(std::string &errorMessage) { m_it = m_level1->begin(); - /*- - If the palette is empty, make an initial palette with black, red, blue and green styles. + /*- + If the palette is empty, make an initial palette with black, red, blue and + green styles. For the latter three styles the "autopaint" option should be set. -*/ if (m_lastIndex == 0) { m_colorMap[TPixel::Black] = ++m_lastIndex; - m_colorMap[TPixel::Red] = ++m_lastIndex; - m_colorMap[TPixel::Blue] = ++m_lastIndex; + m_colorMap[TPixel::Red] = ++m_lastIndex; + m_colorMap[TPixel::Blue] = ++m_lastIndex; m_colorMap[TPixel::Green] = ++m_lastIndex; } diff --git a/toonz/sources/toonzlib/palettecmd.cpp b/toonz/sources/toonzlib/palettecmd.cpp index b0fa7f9..3cc28a1 100644 --- a/toonz/sources/toonzlib/palettecmd.cpp +++ b/toonz/sources/toonzlib/palettecmd.cpp @@ -1173,21 +1173,70 @@ void PaletteCmd::renamePaletteStyle(TPaletteHandle *paletteHandle, // organizePaletteStyle // called in ColorModelViewer::pick() - move selected style to the first page //----------------------------------------------------------------------------- -void PaletteCmd::organizePaletteStyle(TPaletteHandle *paletteHandle, int styleId){ +namespace { + +class setStylePickedPositionUndo final : public TUndo { + TPaletteHandle *m_paletteHandle; // Used in undo and redo to notify change + int m_styleId; + TPaletteP m_palette; + TPoint m_newPos; + TPoint m_oldPos; + +public: + setStylePickedPositionUndo(TPaletteHandle *paletteHandle, int styleId, + const TPoint &newPos) + : m_paletteHandle(paletteHandle), m_styleId(styleId), m_newPos(newPos) { + m_palette = paletteHandle->getPalette(); + assert(m_palette); + TColorStyle *style = m_palette->getStyle(m_styleId); + assert(style); + m_oldPos = style->getPickedPosition(); + } + void undo() const override { + TColorStyle *style = m_palette->getStyle(m_styleId); + assert(style); + style->setPickedPosition(m_oldPos); + m_paletteHandle->notifyColorStyleChanged(false); + } + void redo() const override { + TColorStyle *style = m_palette->getStyle(m_styleId); + assert(style); + style->setPickedPosition(m_newPos); + m_paletteHandle->notifyColorStyleChanged(false); + } + int getSize() const override { return sizeof *this; } + QString getHistoryString() override { + return QObject::tr("Set Picked Position of Style#%1 in Palette%2 : %3,%4") + .arg(QString::number(m_styleId)) + .arg(QString::fromStdWString(m_palette->getPaletteName())) + .arg(QString::number(m_newPos.x)) + .arg(QString::number(m_newPos.y)); + } + int getHistoryType() override { return HistoryType::Palette; } +}; +} + +void PaletteCmd::organizePaletteStyle(TPaletteHandle *paletteHandle, + int styleId, const TPoint &point) { if (!paletteHandle) return; TPalette *palette = paletteHandle->getPalette(); if (!palette) return; // if the style is already in the first page, then do nothing - TPalette::Page* page = palette->getStylePage(styleId); + TPalette::Page *page = palette->getStylePage(styleId); if (!page || page->getIndex() == 0) return; int indexInPage = page->search(styleId); - /* - just call arrangeStyles as tentative implementation. - TODO: store the picked position into the style name somehow - */ + TUndoManager::manager()->beginBlock(); + + // call arrangeStyles() to move style to the first page arrangeStyles(paletteHandle, 0, palette->getPage(0)->getStyleCount(), - page->getIndex(), { indexInPage }); - + page->getIndex(), {indexInPage}); + // then set the picked position + setStylePickedPositionUndo *undo = + new setStylePickedPositionUndo(paletteHandle, styleId, point); + undo->redo(); + TUndoManager::manager()->add(undo); + + TUndoManager::manager()->endBlock(); }