From 01e8e736847773c34cd73a1cfb608ac0170d2135 Mon Sep 17 00:00:00 2001 From: manongjohn <manongjohn@users.noreply.github.com> Date: Sep 05 2019 06:42:04 +0000 Subject: Allow Similar Drawing Substitution with selections (#2577) * Allow Similiar Drawing Substitution with selections --- diff --git a/toonz/sources/toonz/xsheetcmd.cpp b/toonz/sources/toonz/xsheetcmd.cpp index 1544141..731a532 100644 --- a/toonz/sources/toonz/xsheetcmd.cpp +++ b/toonz/sources/toonz/xsheetcmd.cpp @@ -699,64 +699,93 @@ private: int m_row; int m_col; int m_count; + bool m_selected; + TCellSelection::Range m_range; + std::vector<std::pair<int, int>> emptyCells; + typedef std::map<std::pair<int, int>, int> FramesMap; + FramesMap m_frameRanges; public: - DrawingSubtitutionGroupUndo(int dir, int row, int col) - : m_direction(dir), m_col(col), m_row(row) { - m_count = 1; - TXshCell cell = TTool::getApplication() - ->getCurrentScene() - ->getScene() - ->getXsheet() - ->getCell(m_row, m_col); - if (!cell.m_level || - !(cell.m_level->getSimpleLevel() || cell.m_level->getChildLevel() || - cell.m_level->getSoundTextLevel())) - return; + DrawingSubtitutionGroupUndo(int dir, int row, int col, bool selected, + TCellSelection::Range range) + : m_direction(dir) + , m_col(col) + , m_row(row) + , m_selected(selected) + , m_range(range) { + TXsheet *xsh = + TTool::getApplication()->getCurrentScene()->getScene()->getXsheet(); + + if (!selected) { + m_range.m_c0 = col; + m_range.m_r0 = row; + m_range.m_c1 = col; + m_range.m_r1 = row; + } - TFrameId id = cell.m_frameId; - - TXshCell nextCell = TTool::getApplication() - ->getCurrentScene() - ->getScene() - ->getXsheet() - ->getCell(m_row + m_count, m_col); - if (!nextCell.m_level || - !(nextCell.m_level->getSimpleLevel() || - nextCell.m_level->getChildLevel() || - nextCell.m_level->getSoundTextLevel())) - return; + for (int c = m_range.m_c0; c <= m_range.m_c1; c++) { + for (int r = m_range.m_r0; r <= m_range.m_r1; r++) { + TXshCell baseCell = xsh->getCell(r, c); + + // Find the 1st populated cell in the column + if (baseCell.isEmpty()) continue; - TFrameId nextId = nextCell.m_frameId; + FramesMap::key_type frameBaseKey(r, c); + int frameCount = 1; + TXshCell nextCell = xsh->getCell((r + frameCount), c); + while (nextCell == baseCell || + (nextCell.isEmpty() && (r + frameCount) <= m_range.m_r1)) { + if (nextCell.isEmpty()) + emptyCells.push_back(std::make_pair((r + frameCount), c)); - while (id == nextId) { - m_count++; - nextCell = TTool::getApplication() - ->getCurrentScene() - ->getScene() - ->getXsheet() - ->getCell(m_row + m_count, m_col); - nextId = nextCell.m_frameId; + frameCount++; + nextCell = xsh->getCell((r + frameCount), c); + } + m_frameRanges.insert(std::make_pair(frameBaseKey, 0)); + m_frameRanges[frameBaseKey] = frameCount; + r = r + (frameCount - 1); // Skip frames in range we've processed + } } } void undo() const override { - int n = 1; - DrawingSubtitutionUndo::changeDrawing(-m_direction, m_row, m_col); - while (n < m_count) { - DrawingSubtitutionUndo::changeDrawing(-m_direction, m_row + n, m_col); - n++; + TXsheet *xsh = + TTool::getApplication()->getCurrentScene()->getScene()->getXsheet(); + FramesMap::const_iterator ct; + for (ct = m_frameRanges.begin(); ct != m_frameRanges.end(); ++ct) { + int n = 0; + while (n < ct->second) { + int row = ct->first.first + n; + int col = ct->first.second; + std::vector<std::pair<int, int>>::const_iterator it; + bool found = false; + for (it = emptyCells.begin(); it != emptyCells.end(); ++it) { + if (it->first == row && it->second == col) { + xsh->clearCells(row, col); + found = true; + } + } + + if (!found) + DrawingSubtitutionUndo::changeDrawing(-m_direction, row, col); + n++; + } } + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); TApp::instance()->getCurrentScene()->setDirtyFlag(true); } void redo() const override { - int n = 1; - DrawingSubtitutionUndo::changeDrawing(m_direction, m_row, m_col); - while (n < m_count) { - DrawingSubtitutionUndo::changeDrawing(m_direction, m_row + n, m_col); - n++; + FramesMap::const_iterator ct; + for (ct = m_frameRanges.begin(); ct != m_frameRanges.end(); ++ct) { + int n = 0; + while (n < ct->second) { + int row = ct->first.first + n; + int col = ct->first.second; + DrawingSubtitutionUndo::changeDrawing(m_direction, row, col); + n++; + } } TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); TApp::instance()->getCurrentScene()->setDirtyFlag(true); @@ -885,15 +914,19 @@ static void drawingSubstituion(int dir) { } static void drawingSubstituionGroup(int dir) { + TCellSelection *selection = dynamic_cast<TCellSelection *>( + TTool::getApplication()->getCurrentSelection()->getSelection()); + TCellSelection::Range range; + bool selected = false; + if (selection) { + range = selection->getSelectedCells(); + if (!(range.isEmpty())) selected = true; + } int row = TTool::getApplication()->getCurrentFrame()->getFrame(); int col = TTool::getApplication()->getCurrentColumn()->getColumnIndex(); - TXshCell cell = - TApp::instance()->getCurrentScene()->getScene()->getXsheet()->getCell( - row, col); - bool isEmpty = cell.isEmpty(); - if (isEmpty) return; + DrawingSubtitutionGroupUndo *undo = - new DrawingSubtitutionGroupUndo(dir, row, col); + new DrawingSubtitutionGroupUndo(dir, row, col, selected, range); TUndoManager::manager()->add(undo); undo->redo(); }