diff --git a/toonz/sources/include/orientation.h b/toonz/sources/include/orientation.h index ef37228..095a1e1 100644 --- a/toonz/sources/include/orientation.h +++ b/toonz/sources/include/orientation.h @@ -236,8 +236,9 @@ public: } const bool &flag(PredefinedFlag which) const { return _flags.at(which); } - virtual int cellWidth() const = 0; - virtual int cellHeight() const = 0; + virtual int cellWidth() const = 0; + virtual int cellHeight() const = 0; + virtual int foldedCellSize() const = 0; protected: void addRect(PredefinedRect which, const QRect &rect); diff --git a/toonz/sources/toonz/cellselection.cpp b/toonz/sources/toonz/cellselection.cpp index cdf26ab..42a2ee9 100644 --- a/toonz/sources/toonz/cellselection.cpp +++ b/toonz/sources/toonz/cellselection.cpp @@ -12,6 +12,7 @@ #include "menubarcommandids.h" #include "timestretchpopup.h" #include "tapp.h" +#include "xsheetviewer.h" // TnzTools includes #include "tools/toolutils.h" @@ -1489,6 +1490,7 @@ void TCellSelection::pasteCells() { QClipboard *clipboard = QApplication::clipboard(); const QMimeData *mimeData = clipboard->mimeData(); TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + XsheetViewer *viewer = TApp::instance()->getCurrentXsheetViewer(); bool initUndo = false; const TCellKeyframeData *cellKeyframeData = @@ -1504,6 +1506,13 @@ void TCellSelection::pasteCells() { DVGui::error(QObject::tr("No data to paste.")); return; } + + if (viewer && !viewer->orientation()->isVerticalTimeline()) { + int cAdj = cellData->getColCount() - 1; + c0 -= cAdj; + c1 -= cAdj; + } + int oldR0 = r0; int oldC0 = c0; int oldR1 = r1; @@ -2114,6 +2123,14 @@ void TCellSelection::overWritePasteCells() { DVGui::error(QObject::tr("No data to paste.")); return; } + + XsheetViewer *viewer = TApp::instance()->getCurrentXsheetViewer(); + if (viewer && !viewer->orientation()->isVerticalTimeline()) { + int cAdj = cellData->getColCount() - 1; + c0 -= cAdj; + c1 -= cAdj; + } + int oldR0 = r0; int oldC0 = c0; int oldR1 = r1; @@ -2196,6 +2213,13 @@ void TCellSelection::overwritePasteNumbers() { return; } + XsheetViewer *viewer = TApp::instance()->getCurrentXsheetViewer(); + if (viewer && !viewer->orientation()->isVerticalTimeline()) { + int cAdj = cellData->getColCount() - 1; + c0 -= cAdj; + c1 -= cAdj; + } + int oldR0 = r0; int oldC0 = c0; int oldR1 = r1; diff --git a/toonz/sources/toonz/keyframedata.cpp b/toonz/sources/toonz/keyframedata.cpp index cc8e2a6..b3afd6e 100644 --- a/toonz/sources/toonz/keyframedata.cpp +++ b/toonz/sources/toonz/keyframedata.cpp @@ -4,6 +4,7 @@ #include "tapp.h" #include "toonzqt/tselectionhandle.h" #include "keyframeselection.h" +#include "xsheetviewer.h" #include "toonz/txsheet.h" #include "toonz/tstageobjecttree.h" @@ -38,11 +39,18 @@ void TKeyframeData::setKeyframes(std::set<Position> positions, TXsheet *xsh) { std::set<Position>::iterator it = positions.begin(); int r0 = it->first; int c0 = it->second; + int r1 = it->first; + int c1 = it->second; for (++it; it != positions.end(); ++it) { r0 = std::min(r0, it->first); c0 = std::min(c0, it->second); + r1 = std::max(r1, it->first); + c1 = std::max(c1, it->second); } + m_columnSpanCount = c1 - c0 + 1; + m_rowSpanCount = r1 - r0 + 1; + for (it = positions.begin(); it != positions.end(); ++it) { int row = it->first; int col = it->second; @@ -70,6 +78,11 @@ bool TKeyframeData::getKeyframes(std::set<Position> &positions, r0 = std::min(r0, it2->first); c0 = std::min(c0, it2->second); } + + XsheetViewer *viewer = TApp::instance()->getCurrentXsheetViewer(); + if (viewer && !viewer->orientation()->isVerticalTimeline()) + c0 -= m_columnSpanCount - 1; + positions.clear(); TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); Iterator it; diff --git a/toonz/sources/toonz/keyframedata.h b/toonz/sources/toonz/keyframedata.h index 28f8696..3f9aada 100644 --- a/toonz/sources/toonz/keyframedata.h +++ b/toonz/sources/toonz/keyframedata.h @@ -22,6 +22,8 @@ public: typedef std::map<Position, TStageObject::Keyframe>::const_iterator Iterator; KeyData m_keyData; + int m_columnSpanCount; + int m_rowSpanCount; // Numero di colonna della pegbar associato al booleano isCycleEnabled della // pegbar @@ -47,6 +49,9 @@ public: TKeyframeData *data = new TKeyframeData(this); return data; } + + int getColumnSpanCount() const { return m_columnSpanCount; } + int getRowSpanCount() const { return m_rowSpanCount; } }; #endif // KEYFRAMEDATA_INCLUDED diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index 74da027..d859435 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -1812,6 +1812,7 @@ void MainWindow::defineActions() { createMenuXsheetAction(MI_RemoveGlobalKeyframe, tr("Remove Multiple Keys"), ""); createMenuXsheetAction(MI_NewNoteLevel, tr("New Note Level"), ""); + createMenuXsheetAction(MI_RemoveEmptyColumns, tr("Remove Empty Columns"), ""); createMenuXsheetAction(MI_LipSyncPopup, tr("&Apply Lip Sync Data to Column"), "Alt+L"); createRightClickMenuAction(MI_ToggleXSheetToolbar, @@ -2371,9 +2372,9 @@ RecentFiles::~RecentFiles() {} void RecentFiles::addFilePath(QString path, FileType fileType) { QList<QString> files = - (fileType == Scene) - ? m_recentScenes - : (fileType == Level) ? m_recentLevels : m_recentFlipbookImages; + (fileType == Scene) ? m_recentScenes : (fileType == Level) + ? m_recentLevels + : m_recentFlipbookImages; int i; for (i = 0; i < files.size(); i++) if (files.at(i) == path) files.removeAt(i); @@ -2498,9 +2499,9 @@ void RecentFiles::saveRecentFiles() { QList<QString> RecentFiles::getFilesNameList(FileType fileType) { QList<QString> files = - (fileType == Scene) - ? m_recentScenes - : (fileType == Level) ? m_recentLevels : m_recentFlipbookImages; + (fileType == Scene) ? m_recentScenes : (fileType == Level) + ? m_recentLevels + : m_recentFlipbookImages; QList<QString> names; int i; for (i = 0; i < files.size(); i++) { @@ -2527,9 +2528,9 @@ void RecentFiles::refreshRecentFilesMenu(FileType fileType) { menu->setEnabled(false); else { CommandId clearActionId = - (fileType == Scene) - ? MI_ClearRecentScene - : (fileType == Level) ? MI_ClearRecentLevel : MI_ClearRecentImage; + (fileType == Scene) ? MI_ClearRecentScene : (fileType == Level) + ? MI_ClearRecentLevel + : MI_ClearRecentImage; menu->setActions(names); menu->addSeparator(); QAction *clearAction = CommandManager::instance()->getAction(clearActionId); diff --git a/toonz/sources/toonz/menubar.cpp b/toonz/sources/toonz/menubar.cpp index 6212f2a..65d241a 100644 --- a/toonz/sources/toonz/menubar.cpp +++ b/toonz/sources/toonz/menubar.cpp @@ -1233,6 +1233,7 @@ QMenuBar *StackedMenuBar::createFullMenuBar() { addMenuItem(xsheetMenu, MI_InsertFx); addMenuItem(xsheetMenu, MI_NewOutputFx); addMenuItem(xsheetMenu, MI_NewNoteLevel); + addMenuItem(xsheetMenu, MI_RemoveEmptyColumns); xsheetMenu->addSeparator(); addMenuItem(xsheetMenu, MI_InsertSceneFrame); addMenuItem(xsheetMenu, MI_RemoveSceneFrame); diff --git a/toonz/sources/toonz/menubarcommandids.h b/toonz/sources/toonz/menubarcommandids.h index 0543d9f..eea6be2 100644 --- a/toonz/sources/toonz/menubarcommandids.h +++ b/toonz/sources/toonz/menubarcommandids.h @@ -39,6 +39,7 @@ #define MI_LoadColorModel "MI_LoadColorModel" #define MI_ImportMagpieFile "MI_ImportMagpieFile" #define MI_NewNoteLevel "MI_NewNoteLevel" +#define MI_RemoveEmptyColumns "MI_RemoveEmptyColumns" #define MI_NewProject "MI_NewProject" #define MI_ProjectSettings "MI_ProjectSettings" #define MI_SaveDefaultSettings "MI_SaveDefaultSettings" diff --git a/toonz/sources/toonz/tapp.h b/toonz/sources/toonz/tapp.h index d52df8d..2779ee0 100644 --- a/toonz/sources/toonz/tapp.h +++ b/toonz/sources/toonz/tapp.h @@ -26,6 +26,7 @@ class QMainWindow; class TMainWindow; class ComboViewerPanel; class SceneViewer; +class XsheetViewer; //============================================================================= // TXsheeHandle @@ -84,6 +85,7 @@ class TApp final : public QObject, // the filmstrip ComboViewerPanel *m_inknPaintViewerPanel; SceneViewer *m_activeViewer; + XsheetViewer *m_xsheetViewer; int m_autosavePeriod; // minutes bool m_autosaveSuspended; @@ -207,6 +209,10 @@ public: void writeSettings(); + void setCurrentXsheetViewer(XsheetViewer *viewer) { m_xsheetViewer = viewer; } + + XsheetViewer *getCurrentXsheetViewer() const { return m_xsheetViewer; } + protected: bool eventFilter(QObject *obj, QEvent *event) override; diff --git a/toonz/sources/toonz/xshcellmover.cpp b/toonz/sources/toonz/xshcellmover.cpp index da4797b..303a233 100644 --- a/toonz/sources/toonz/xshcellmover.cpp +++ b/toonz/sources/toonz/xshcellmover.cpp @@ -7,6 +7,7 @@ #include "xsheetviewer.h" #include "cellselection.h" #include "columncommand.h" +#include "columnselection.h" // TnzTools includes #include "tools/cursors.h" @@ -30,6 +31,7 @@ #include "toonz/fxdag.h" #include "toonz/tcolumnfxset.h" #include "toonz/txshleveltypes.h" +#include "toonz/tcolumnhandle.h" // TnzBase includes #include "tfx.h" @@ -48,7 +50,8 @@ CellsMover::CellsMover() , m_startPos(0, 0) , m_columnsData(0) , m_qualifiers(0) - , m_uffa(0) {} + , m_uffa(0) + , m_orientation(nullptr) {} CellsMover::~CellsMover() { delete m_columnsData; @@ -58,13 +61,16 @@ CellsMover::~CellsMover() { // // initialize the mover: allocate memory, get cells and column data // -void CellsMover::start(int r0, int c0, int r1, int c1, int qualifiers) { +void CellsMover::start(int r0, int c0, int r1, int c1, int qualifiers, + const Orientation *o) { m_rowCount = r1 - r0 + 1; m_colCount = c1 - c0 + 1; assert(m_rowCount > 0); assert(m_colCount > 0); - m_startPos = m_pos = TPoint(c0, r0); - m_qualifiers = qualifiers; + m_orientation = o; + m_startPos = m_pos = + (o->isVerticalTimeline() ? TPoint(c0, r0) : TPoint(r0, c0)); + m_qualifiers = qualifiers; m_cells.resize(m_rowCount * m_colCount, TXshCell()); m_oldCells.resize(m_rowCount * m_colCount, TXshCell()); getCells(m_cells, r0, c0); @@ -112,6 +118,10 @@ void CellsMover::setCells(const std::vector<TXshCell> &cells, int r, void CellsMover::saveCells() { int r = m_pos.y; int c = m_pos.x; + if (!getOrientation()->isVerticalTimeline()) { + r = m_pos.x; + c = m_pos.y; + } getCells(m_oldCells, r, c); } @@ -119,8 +129,12 @@ void CellsMover::saveCells() { // xsheet <- m_cells; insert cells if qualifiers contain eInsertCells // void CellsMover::moveCells(const TPoint &pos) const { - int r = pos.y; - int c = pos.x; + int r = pos.y; + int c = pos.x; + if (!getOrientation()->isVerticalTimeline()) { + r = pos.x; + c = pos.y; + } TXsheet *xsh = getXsheet(); if (m_qualifiers & eInsertCells) { for (int i = 0; i < m_colCount; i++) { @@ -138,6 +152,10 @@ void CellsMover::undoMoveCells(const TPoint &pos) const { TXsheet *xsh = getXsheet(); int r = pos.y; int c = pos.x; + if (!m_orientation->isVerticalTimeline()) { + r = pos.x; + c = pos.y; + } if (m_qualifiers & eInsertCells) { for (int i = 0; i < m_colCount; i++) xsh->removeCells(r, c + i, m_rowCount); } else { @@ -148,14 +166,22 @@ void CellsMover::undoMoveCells(const TPoint &pos) const { bool CellsMover::canMoveCells(const TPoint &pos) { TXsheet *xsh = getXsheet(); - if (pos.x < 0) return false; - if (pos.x != m_startPos.x) { + int r = pos.y; + int c = pos.x; + int cStart = m_startPos.x; + if (!m_orientation->isVerticalTimeline()) { + r = pos.x; + c = pos.y; + cStart = m_startPos.y; + } + if (c < 0) return false; + if (c != cStart) { int count = 0; // controlla il tipo int i = 0; while (i < m_rowCount * m_colCount) { TXshColumn::ColumnType srcType = getColumnTypeFromCell(i); - int dstIndex = pos.x + i; + int dstIndex = c + i; TXshColumn *dstColumn = xsh->getColumn(dstIndex); if (srcType == TXshColumn::eZeraryFxType || srcType == TXshColumn::eSoundTextType) @@ -174,7 +200,7 @@ bool CellsMover::canMoveCells(const TPoint &pos) { int count = 0; for (int i = 0; i < m_colCount; i++) { for (int j = 0; j < m_rowCount; j++) { - if (!xsh->getCell(pos.y + j, pos.x + i).isEmpty()) return false; + if (!xsh->getCell(r + j, c + i).isEmpty()) return false; count++; } } @@ -255,17 +281,34 @@ public: CellsMover *getCellsMover() { return &m_cellsMover; } void undo() const override { - m_cellsMover.undoMoveCells(); + if (m_cellsMover.getOrientation()->isVerticalTimeline()) + m_cellsMover.undoMoveCells(); + else { + int r = m_cellsMover.getPos().y; + int c = m_cellsMover.getPos().x; + m_cellsMover.undoMoveCells(TPoint(c, r)); + } int ca = m_cellsMover.getStartPos().x; int cb = m_cellsMover.getPos().x; int colCount = m_cellsMover.getColumnCount(); + if (!m_cellsMover.getOrientation()->isVerticalTimeline()) { + ca = m_cellsMover.getStartPos().y; + cb = m_cellsMover.getPos().y; + } if (ca != cb) { if (m_cellsMover.m_uffa & 2) m_cellsMover.emptyColumns(cb); if (m_cellsMover.m_uffa & 1) m_cellsMover.restoreColumns(ca); } - m_cellsMover.moveCells(m_cellsMover.getStartPos()); + if (m_cellsMover.getOrientation()->isVerticalTimeline()) + m_cellsMover.moveCells(m_cellsMover.getStartPos()); + else { + int rStart = m_cellsMover.getStartPos().x; + int cStart = m_cellsMover.getStartPos().y; + const TPoint useStart(rStart, cStart); + m_cellsMover.moveCells(useStart); + } TApp::instance()->getCurrentXsheet()->getXsheet()->updateFrameCount(); TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); if (m_cellsMover.getColumnTypeFromCell(0) == TXshColumn::eSoundType) @@ -275,6 +318,10 @@ public: int ca = m_cellsMover.getStartPos().x; int cb = m_cellsMover.getPos().x; int colCount = m_cellsMover.getColumnCount(); + if (!m_cellsMover.getOrientation()->isVerticalTimeline()) { + int ca = m_cellsMover.getStartPos().y; + int cb = m_cellsMover.getPos().y; + } if (ca != cb) { if (m_cellsMover.m_uffa & 1) m_cellsMover.emptyColumns(ca); @@ -288,7 +335,9 @@ public: CellsMover::eOverwriteCells) { // rimuove le celle vecchie int c, ra = m_cellsMover.getStartPos().y, rowCount = m_cellsMover.getRowCount(); - TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + if (!m_cellsMover.getOrientation()->isVerticalTimeline()) + ra = m_cellsMover.getStartPos().x; + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); for (c = ca; c < ca + colCount; c++) xsh->clearCells(ra, c, rowCount); } m_cellsMover.moveCells(); @@ -338,14 +387,23 @@ bool LevelMoverTool::canMove(const TPoint &pos) { } bool LevelMoverTool::canMoveColumns(const TPoint &pos) { - TXsheet *xsh = getViewer()->getXsheet(); - if (pos.x < 0) return false; - if (pos.x != m_lastPos.x) { + const Orientation *o = getViewer()->orientation(); + TXsheet *xsh = getViewer()->getXsheet(); + int c = pos.x; + int cLast = m_lastPos.x; + int cRange = m_range.lx; + if (!o->isVerticalTimeline()) { + c = pos.y; + cLast = m_lastPos.y; + cRange = m_range.ly; + } + if (c < 0) return false; + if (c != cLast) { int count = 0; // controlla il tipo - for (int i = 0; i < m_range.lx; i++) { - int srcIndex = m_lastPos.x + i; - int dstIndex = pos.x + i; + for (int i = 0; i < cRange; i++) { + int srcIndex = cLast + i; + int dstIndex = c + i; TXshColumn *srcColumn = xsh->getColumn(srcIndex); if (srcColumn && srcColumn->isLocked()) continue; TXshColumn *dstColumn = xsh->getColumn(dstIndex); @@ -353,11 +411,11 @@ bool LevelMoverTool::canMoveColumns(const TPoint &pos) { if (srcColumn) srcType = srcColumn->getColumnType(); if (srcType == TXshColumn::eZeraryFxType) return false; /* -qDebug() << "check: " << srcIndex << ":" << -(srcColumn ? QString::number(srcType) : "empty") << -" => " << dstIndex << ":" << -(dstColumn ? QString::number(dstColumn->getColumnType()) : "empty"); -*/ + qDebug() << "check: " << srcIndex << ":" << + (srcColumn ? QString::number(srcType) : "empty") << + " => " << dstIndex << ":" << + (dstColumn ? QString::number(dstColumn->getColumnType()) : "empty"); + */ if (dstColumn && !dstColumn->isEmpty() && dstColumn->getColumnType() != srcType) { @@ -373,6 +431,7 @@ qDebug() << "check: " << srcIndex << ":" << } void LevelMoverTool::onClick(const QMouseEvent *e) { + const Orientation *o = getViewer()->orientation(); QPoint pos = e->pos(); CellPosition cellPosition = getViewer()->xyToPosition(e->pos()); int row = cellPosition.frame(); @@ -399,7 +458,8 @@ void LevelMoverTool::onClick(const QMouseEvent *e) { m_validPos = true; m_undo = new LevelMoverUndo(); CellsMover *cellsMover = m_undo->getCellsMover(); - cellsMover->start(r0, c0, r1, c1, m_qualifiers); + XsheetViewer *viewer = getViewer(); + cellsMover->start(r0, c0, r1, c1, m_qualifiers, o); m_undo->m_columnsChanges.resize(c1 - c0 + 1, 0); m_moved = true; @@ -414,12 +474,13 @@ void LevelMoverTool::onClick(const QMouseEvent *e) { int colCount = c1 - c0 + 1; int rowCount = r1 - r0 + 1; - m_range.lx = colCount; - m_range.ly = rowCount; - m_startPos.x = c0; - m_startPos.y = r0; + m_range.lx = o->isVerticalTimeline() ? colCount : rowCount; + m_range.ly = o->isVerticalTimeline() ? rowCount : colCount; + m_startPos.x = o->isVerticalTimeline() ? c0 : r0; + m_startPos.y = o->isVerticalTimeline() ? r0 : c0; m_lastPos = m_aimedPos = m_startPos; - m_grabOffset = m_startPos - TPoint(col, row); + m_grabOffset = m_startPos - (o->isVerticalTimeline() ? TPoint(col, row) + : TPoint(row, col)); TXsheet *xsh = getViewer()->getXsheet(); @@ -427,35 +488,80 @@ void LevelMoverTool::onClick(const QMouseEvent *e) { m_validPos = true; m_lastPos = m_startPos; m_undo->getCellsMover()->m_uffa = 0; + + if (!getViewer()->orientation()->isVerticalTimeline()) + TUndoManager::manager()->beginBlock(); } void LevelMoverTool::onCellChange(int row, int col) { - TXsheet *xsh = getViewer()->getXsheet(); + const Orientation *o = getViewer()->orientation(); + TXsheet *xsh = getViewer()->getXsheet(); - TPoint pos = TPoint(col, row) + m_grabOffset; + TPoint pos = (o->isVerticalTimeline() ? TPoint(col, row) : TPoint(row, col)) + + m_grabOffset; + int origX = pos.x; + int origY = pos.y; if (pos.y < 0) pos.y = 0; - if (pos.x < 0) return; + if (pos.x < 0) pos.x = 0; + + TPoint delta = pos - m_aimedPos; + int dCol = delta.x; + if (!o->isVerticalTimeline()) dCol = delta.y; + + CellsMover *cellsMover = m_undo->getCellsMover(); + std::set<int> ii; + TRect currSelection(m_aimedPos, m_range); + if (!o->isVerticalTimeline()) { + if (origY < 0) dCol += origY; + int newBegin = currSelection.y0 + dCol; + if (newBegin < 0) { + newBegin *= -1; + for (int y = 0; y < newBegin; y++) ii.insert(y); + ColumnCmd::insertEmptyColumns(ii); + m_lastPos += TPoint(0, newBegin); + m_startPos += TPoint(0, newBegin); + m_aimedPos += TPoint(0, newBegin); + cellsMover->setStartPos(cellsMover->getStartPos() + TPoint(0, newBegin)); + cellsMover->setPos(cellsMover->getPos() + TPoint(0, newBegin)); + // getViewer()->setCurrentColumn(getViewer()->getCurrentColumn() + //+ newBegin); + pos.x = origY + newBegin; + } else { + int maxY = xsh->getColumnCount() - 1; + int newEnd = currSelection.y1 + dCol; + if (newEnd > maxY) { + for (int y = maxY + 1; y <= newEnd; y++) ii.insert(y); + ColumnCmd::insertEmptyColumns(ii); + } + } + } if (pos == m_aimedPos) return; - m_aimedPos = pos; - TPoint delta = m_aimedPos - m_lastPos; + m_aimedPos = pos; m_validPos = canMoveColumns(pos); if (!m_validPos) return; - - CellsMover *cellsMover = m_undo->getCellsMover(); if (m_moved) cellsMover->undoMoveCells(); m_validPos = canMove(pos); if (m_validPos) { //---------------------- - if (delta.x != 0 && (m_qualifiers & CellsMover::eMoveColumns)) { + if (dCol != 0 && (m_qualifiers & CellsMover::eMoveColumns)) { // spostamento di colonne int colCount = m_range.lx; + int colLast = m_lastPos.x; + int colPos = pos.x; + int colStart = m_startPos.x; + if (!o->isVerticalTimeline()) { + colCount = m_range.ly; + colLast = m_lastPos.y; + colPos = pos.y; + colStart = m_startPos.y; + } bool emptySrc = true; for (int i = 0; i < colCount; i++) { - TXshColumn *column = xsh->getColumn(m_lastPos.x + i); + TXshColumn *column = xsh->getColumn(colLast + i); if (column && !column->isEmpty()) { emptySrc = false; break; @@ -465,26 +571,26 @@ void LevelMoverTool::onCellChange(int row, int col) { bool lockedDst = false; bool emptyDst = true; for (int i = 0; i < colCount; i++) { - if (!isTotallyEmptyColumn(pos.x + i)) emptyDst = false; - TXshColumn *column = xsh->getColumn(pos.x + i); + if (!isTotallyEmptyColumn(colPos + i)) emptyDst = false; + TXshColumn *column = xsh->getColumn(colPos + i); if (column && column->isLocked()) lockedDst = true; } if (emptySrc) { - if (m_lastPos.x == m_startPos.x) + if (colLast == colStart) m_undo->getCellsMover()->m_uffa |= 1; // first column(s) has/have been cleared - cellsMover->emptyColumns(m_lastPos.x); + cellsMover->emptyColumns(colLast); } if (emptyDst && !lockedDst) { - if (pos.x == m_startPos.x) + if (colPos == colStart) m_undo->getCellsMover()->m_uffa &= ~1; // first column(s) has/have been restored else m_undo->getCellsMover()->m_uffa |= 2; // columns data have been copied on the current position - cellsMover->restoreColumns(pos.x); + cellsMover->restoreColumns(colPos); } else { m_undo->getCellsMover()->m_uffa &= ~2; // no columns data have been copied on the current position @@ -507,8 +613,12 @@ void LevelMoverTool::onCellChange(int row, int col) { if (cellsMover->getColumnTypeFromCell(0) == TXshColumn::eSoundType) TApp::instance()->getCurrentXsheet()->notifyXsheetSoundChanged(); TRect selection(m_aimedPos, m_range); - getViewer()->getCellSelection()->selectCells(selection.y0, selection.x0, - selection.y1, selection.x1); + if (o->isVerticalTimeline()) + getViewer()->getCellSelection()->selectCells(selection.y0, selection.x0, + selection.y1, selection.x1); + else + getViewer()->getCellSelection()->selectCells(selection.x0, selection.y0, + selection.x1, selection.y1); } void LevelMoverTool::onDrag(const QMouseEvent *e) { @@ -524,11 +634,20 @@ void LevelMoverTool::onRelease(const CellPosition &pos) { m_range.ly = 0; setToolCursor(getViewer(), ToolCursor::CURSOR_ARROW); refreshCellsArea(); + CellsMover *cellMover = m_undo->getCellsMover(); + int startX = cellMover->getStartPos().x; + int startY = cellMover->getStartPos().y; + int posX = cellMover->getPos().x; + int posY = cellMover->getPos().y; if (m_lastPos != m_startPos) TUndoManager::manager()->add(m_undo); m_undo = 0; + + if (!getViewer()->orientation()->isVerticalTimeline()) + TUndoManager::manager()->endBlock(); } void LevelMoverTool::drawCellsArea(QPainter &p) { + const Orientation *o = getViewer()->orientation(); TRect rect(m_aimedPos, m_range); // voglio visualizzare il rettangolo nella posizione desiderata // che potrebbe anche non essere possibile, ad esempio perche' fuori @@ -538,8 +657,17 @@ void LevelMoverTool::drawCellsArea(QPainter &p) { if (rect.x0 < 0) rect.x0 = 0; if (rect.y0 < 0) rect.y0 = 0; - QRect screen = getViewer()->rangeToXYRect(CellRange( - CellPosition(rect.y0, rect.x0), CellPosition(rect.y1 + 1, rect.x1 + 1))); + QRect screen; + if (o->isVerticalTimeline()) + screen = getViewer()->rangeToXYRect( + CellRange(CellPosition(rect.y0, rect.x0), + CellPosition(rect.y1 + 1, rect.x1 + 1))); + else { + int newY0 = qMax(rect.y0, rect.y1); + int newY1 = qMin(rect.y0, rect.y1); + screen = getViewer()->rangeToXYRect(CellRange( + CellPosition(rect.x0, newY0), CellPosition(rect.x1 + 1, newY1 - 1))); + } p.setPen((m_aimedPos == m_lastPos && m_validPos) ? QColor(190, 220, 255) : QColor(255, 0, 0)); int i; diff --git a/toonz/sources/toonz/xshcellmover.h b/toonz/sources/toonz/xshcellmover.h index ef54568..28d36bd 100644 --- a/toonz/sources/toonz/xshcellmover.h +++ b/toonz/sources/toonz/xshcellmover.h @@ -9,6 +9,7 @@ #include "tundo.h" #include <QMap> #include "xsheetdragtool.h" +#include "orientation.h" #include <set> @@ -30,6 +31,8 @@ class CellsMover { // bitmask of qualifiers that change the behaviour of the Mover int m_qualifiers; + const Orientation *m_orientation; + // helper method TXsheet *getXsheet() const; @@ -58,7 +61,8 @@ public: int m_uffa; // initialize the Mover - void start(int r0, int c0, int r1, int c1, int qualifiers); + void start(int r0, int c0, int r1, int c1, int qualifiers, + const Orientation *o); int getQualifiers() const { return m_qualifiers; } TPoint getStartPos() const { return m_startPos; } @@ -66,6 +70,8 @@ public: int getColumnCount() const { return m_colCount; } int getRowCount() const { return m_rowCount; } + void setStartPos(const TPoint &p) { m_startPos = p; } + void setStartPos(int r, int c) { setStartPos(TPoint(c, r)); } void setPos(const TPoint &p) { m_pos = p; } void setPos(int r, int c) { setPos(TPoint(c, r)); } @@ -80,6 +86,8 @@ public: void emptyColumns(int c) const; TXshColumn::ColumnType getColumnTypeFromCell(int index) const; + const Orientation *getOrientation() const { return m_orientation; } + private: // not implemented CellsMover(const CellsMover &); diff --git a/toonz/sources/toonz/xshcellviewer.cpp b/toonz/sources/toonz/xshcellviewer.cpp index 6eec2eb..e8ec756 100644 --- a/toonz/sources/toonz/xshcellviewer.cpp +++ b/toonz/sources/toonz/xshcellviewer.cpp @@ -1037,14 +1037,14 @@ void CellArea::setDragTool(DragTool *dragTool) { void CellArea::drawCells(QPainter &p, const QRect toBeUpdated) { TXsheet *xsh = m_viewer->getXsheet(); - ColumnFan *columnFan = xsh->getColumnFan(m_viewer->orientation()); + const Orientation *o = m_viewer->orientation(); + ColumnFan *columnFan = xsh->getColumnFan(o); // selected cells range TCellSelection *cellSelection = m_viewer->getCellSelection(); int rS0, cS0, rS1, cS1; if (!cellSelection->isEmpty()) cellSelection->getSelectedCells(rS0, cS0, rS1, cS1); - // visible cells range CellRange visible = m_viewer->xyRectToRange(toBeUpdated); int r0, r1, c0, c1; // range of visible rows and columns @@ -1052,6 +1052,10 @@ void CellArea::drawCells(QPainter &p, const QRect toBeUpdated) { r1 = visible.to().frame(); c0 = visible.from().layer(); c1 = visible.to().layer(); + if (!m_viewer->orientation()->isVerticalTimeline()) { + int colCount = qMax(1, xsh->getColumnCount()); + c1 = qMin(c1, colCount - 1); + } drawNonEmptyBackground(p); @@ -1120,6 +1124,10 @@ void CellArea::drawCells(QPainter &p, const QRect toBeUpdated) { NumberRange layerAxisRange(layerAxis + 1, m_viewer->columnToLayerAxis(col + 1)); + if (!m_viewer->orientation()->isVerticalTimeline()) { + int adjY = m_viewer->orientation()->cellHeight() - 1; + layerAxisRange = NumberRange(layerAxis + 1, layerAxis + adjY); + } // draw vertical line if (layerAxis > 0) { @@ -1190,9 +1198,21 @@ void CellArea::drawNonEmptyBackground(QPainter &p) const { if (!currentColumn) continue; if (!currentColumn->isEmpty()) break; } - QPoint xy = - m_viewer->positionToXY(CellPosition(totalFrames, lastNonEmptyCol + 1)); - p.fillRect(1, 0, xy.x(), xy.y(), QBrush(m_viewer->getNotEmptyColumnColor())); + QPoint xyTop, xyBottom; + const Orientation *o = m_viewer->orientation(); + if (o->isVerticalTimeline()) { + xyTop = QPoint(1, 0); + xyBottom = + m_viewer->positionToXY(CellPosition(totalFrames, lastNonEmptyCol + 1)); + } else { + xyTop = m_viewer->positionToXY(CellPosition(0, lastNonEmptyCol)); + xyBottom = m_viewer->positionToXY(CellPosition(totalFrames, 0)); + ColumnFan *fan = xsh->getColumnFan(o); + xyBottom.setY(xyBottom.y() + + ((fan ? fan->isActive(0) : true) ? o->cellHeight() : 9)); + } + p.fillRect(xyTop.x(), xyTop.y(), xyBottom.x(), xyBottom.y(), + QBrush(m_viewer->getNotEmptyColumnColor())); } void CellArea::drawFoldedColumns(QPainter &p, int layerAxis, @@ -1220,8 +1240,20 @@ void CellArea::drawSelectionBackground(QPainter &p) const { int selRow0, selCol0, selRow1, selCol1; cellSelection->getSelectedCells(selRow0, selCol0, selRow1, selCol1); - QRect selectionRect = m_viewer->rangeToXYRect(CellRange( - CellPosition(selRow0, selCol0), CellPosition(selRow1 + 1, selCol1 + 1))); + QRect selectionRect; + const Orientation *o = m_viewer->orientation(); + if (o->isVerticalTimeline()) + selectionRect = m_viewer->rangeToXYRect( + CellRange(CellPosition(selRow0, selCol0), + CellPosition(selRow1 + 1, selCol1 + 1))); + else { + int newSelCol0 = qMax(selCol0, selCol1); + int newSelCol1 = qMin(selCol0, selCol1); + selectionRect = m_viewer->rangeToXYRect( + CellRange(CellPosition(selRow0, newSelCol0), + CellPosition(selRow1 + 1, newSelCol1 - 1))); + } + p.fillRect(selectionRect, QBrush(m_viewer->getSelectedEmptyCellColor())); } @@ -1237,8 +1269,16 @@ void CellArea::drawExtenderHandles(QPainter &p) { int selRow0, selCol0, selRow1, selCol1; cellSelection->getSelectedCells(selRow0, selCol0, selRow1, selCol1); - QRect selected = m_viewer->rangeToXYRect(CellRange( + QRect selected; + selected = m_viewer->rangeToXYRect(CellRange( CellPosition(selRow0, selCol0), CellPosition(selRow1 + 1, selCol1 + 1))); + if (!o->isVerticalTimeline()) { + TXsheet *xsh = m_viewer->getXsheet(); + ColumnFan *columnFan = xsh->getColumnFan(o); + int topAdj = columnFan->isActive(selCol0) ? o->cellHeight() : 9; + int bottomAdj = columnFan->isActive(selCol1) ? o->cellHeight() : 9; + selected.adjust(0, topAdj, 0, bottomAdj); + } int x0, y0, x1, y1; x0 = selected.left(); @@ -1456,6 +1496,18 @@ void CellArea::drawSoundCell(QPainter &p, int row, int col, bool isReference) { if (r1 != r1WithoutOff) p.fillRect(modifierRect, SoundColumnExtenderColor); m_soundLevelModifyRects.append(modifierRect); } + + int distance, markerOffset; + TApp::instance()->getCurrentScene()->getScene()->getProperties()->getMarkers( + distance, markerOffset); + bool isAfterMarkers = + (row - markerOffset) % distance == 0 && distance != 0 && row != 0; + + // draw marker interval + if (isAfterMarkers) { + p.setPen(m_viewer->getMarkerLineColor()); + p.drawLine(o->line(PredefinedLine::SEE_MARKER_THROUGH).translated(xy)); + } } //----------------------------------------------------------------------------- @@ -2461,7 +2513,9 @@ void CellArea::mousePressEvent(QMouseEvent *event) { m_viewer->getKeyframeSelection()->selectNone(); setDragTool(XsheetGUI::DragTool::makeLevelExtenderTool(m_viewer, true)); } else if ((!xsh->getCell(row, col).isEmpty()) && - o->rect(PredefinedRect::DRAG_AREA).contains(mouseInCell)) { + o->rect(PredefinedRect::DRAG_AREA) + .adjusted(0, 0, -frameAdj, 0) + .contains(mouseInCell)) { TXshColumn *column = xsh->getColumn(col); if (column && !m_viewer->getCellSelection()->isCellSelected(row, col)) { int r0, r1; @@ -2487,7 +2541,9 @@ void CellArea::mousePressEvent(QMouseEvent *event) { } else { m_viewer->getKeyframeSelection()->selectNone(); if (isSoundColumn && - o->rect(PredefinedRect::PREVIEW_TRACK).contains(mouseInCell)) + o->rect(PredefinedRect::PREVIEW_TRACK) + .adjusted(0, 0, -frameAdj, 0) + .contains(mouseInCell)) setDragTool(XsheetGUI::DragTool::makeSoundScrubTool( m_viewer, column->getSoundColumn())); else if (isSoundColumn && @@ -2559,10 +2615,11 @@ void CellArea::mouseMoveEvent(QMouseEvent *event) { bool isKeyframeFrame = Preferences::instance()->isShowKeyframesOnXsheetCellAreaEnabled() && pegbar && pegbar->getKeyframeRange(k0, k1) && k0 <= row && row <= k1 + 1; - bool isKeyFrameArea = - isKeyframeFrame && - o->rect(PredefinedRect::KEYFRAME_AREA).contains(mouseInCell) && - row < k1 + 1; + bool isKeyFrameArea = isKeyframeFrame && + o->rect(PredefinedRect::KEYFRAME_AREA) + .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) + .contains(mouseInCell) && + row < k1 + 1; if (isKeyFrameArea) { if (pegbar->isKeyframe(row)) // key frame @@ -2586,7 +2643,9 @@ void CellArea::mouseMoveEvent(QMouseEvent *event) { .contains(mouseInCell)) // cycle toggle of key frames m_tooltip = tr("Set the cycle of previous keyframes"); else if ((!xsh->getCell(row, col).isEmpty()) && - o->rect(PredefinedRect::DRAG_AREA).contains(mouseInCell)) + o->rect(PredefinedRect::DRAG_AREA) + .adjusted(0, 0, -frameAdj, 0) + .contains(mouseInCell)) m_tooltip = tr("Click and drag to move the selection"); else if (isZeraryColumn) m_tooltip = QString::fromStdWString(column->getZeraryFxColumn() @@ -2618,7 +2677,9 @@ void CellArea::mouseMoveEvent(QMouseEvent *event) { QString::fromStdString(frameNumber)); } } else if (isSoundColumn && - o->rect(PredefinedRect::PREVIEW_TRACK).contains(mouseInCell)) + o->rect(PredefinedRect::PREVIEW_TRACK) + .adjusted(0, 0, -frameAdj, 0) + .contains(mouseInCell)) m_tooltip = tr("Click and drag to play"); else if (m_levelExtenderRect.contains(pos)) m_tooltip = tr("Click and drag to repeat selected cells"); @@ -2646,6 +2707,7 @@ void CellArea::mouseReleaseEvent(QMouseEvent *event) { void CellArea::mouseDoubleClickEvent(QMouseEvent *event) { const Orientation *o = m_viewer->orientation(); + int frameAdj = m_viewer->getFrameZoomAdjustment(); TPoint pos(event->pos().x(), event->pos().y()); CellPosition cellPosition = m_viewer->xyToPosition(event->pos()); int row = cellPosition.frame(); @@ -2680,10 +2742,11 @@ void CellArea::mouseDoubleClickEvent(QMouseEvent *event) { int k0, k1; bool isKeyframeFrame = pegbar && pegbar->getKeyframeRange(k0, k1) && k0 <= row && row <= k1 + 1; - bool isKeyFrameArea = - isKeyframeFrame && - o->rect(PredefinedRect::KEYFRAME_AREA).contains(mouseInCell) && - row < k1 + 1; + bool isKeyFrameArea = isKeyframeFrame && + o->rect(PredefinedRect::KEYFRAME_AREA) + .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) + .contains(mouseInCell) && + row < k1 + 1; // If you are in the keyframe area, open a function editor if (isKeyFrameArea) { @@ -2711,6 +2774,7 @@ void CellArea::mouseDoubleClickEvent(QMouseEvent *event) { void CellArea::contextMenuEvent(QContextMenuEvent *event) { const Orientation *o = m_viewer->orientation(); + int frameAdj = m_viewer->getFrameZoomAdjustment(); TPoint pos(event->pos().x(), event->pos().y()); CellPosition cellPosition = m_viewer->xyToPosition(event->pos()); int row = cellPosition.frame(); @@ -2747,10 +2811,11 @@ void CellArea::contextMenuEvent(QContextMenuEvent *event) { bool isKeyframeFrame = Preferences::instance()->isShowKeyframesOnXsheetCellAreaEnabled() && pegbar && pegbar->getKeyframeRange(k0, k1) && k0 <= row && row <= k1 + 1; - bool isKeyFrameArea = - isKeyframeFrame && - o->rect(PredefinedRect::KEYFRAME_AREA).contains(mouseInCell) && - row < k1 + 1; + bool isKeyFrameArea = isKeyframeFrame && + o->rect(PredefinedRect::KEYFRAME_AREA) + .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) + .contains(mouseInCell) && + row < k1 + 1; if (isKeyFrameArea) { TStageObjectId objectId; @@ -3028,13 +3093,14 @@ void CellArea::createCellMenu(QMenu &menu, bool isCellSelected) { } else if (selectionContainTlvImage(m_viewer->getCellSelection(), m_viewer->getXsheet())) menu.addAction(cmdManager->getAction(MI_CanvasSize)); - if (sl || (TApp::instance()->getCurrentLevel()->getLevel() && TApp::instance()->getCurrentLevel()->getLevel()->getChildLevel())) + if (sl || + (TApp::instance()->getCurrentLevel()->getLevel() && + TApp::instance()->getCurrentLevel()->getLevel()->getChildLevel())) menu.addAction(cmdManager->getAction(MI_LipSyncPopup)); } menu.addSeparator(); if (!soundCellsSelected) menu.addAction(cmdManager->getAction(MI_ImportMagpieFile)); - } //----------------------------------------------------------------------------- /*! replace level with another level in the cast diff --git a/toonz/sources/toonz/xshcolumnviewer.cpp b/toonz/sources/toonz/xshcolumnviewer.cpp index b8509fb..a7a89ee 100644 --- a/toonz/sources/toonz/xshcolumnviewer.cpp +++ b/toonz/sources/toonz/xshcolumnviewer.cpp @@ -1515,12 +1515,16 @@ void ColumnArea::paintEvent(QPaintEvent *event) { // AREA QPainter p(this); p.setClipRect(toBeUpdated); + TXsheet *xsh = m_viewer->getXsheet(); CellRange cellRange = m_viewer->xyRectToRange(toBeUpdated); int c0, c1; // range of visible columns c0 = cellRange.from().layer(); c1 = cellRange.to().layer(); + if (!m_viewer->orientation()->isVerticalTimeline()) { + int colCount = qMax(1, xsh->getColumnCount()); + c1 = qMin(c1, colCount - 1); + } - TXsheet *xsh = m_viewer->getXsheet(); ColumnFan *columnFan = xsh->getColumnFan(m_viewer->orientation()); int col; for (col = c0; col <= c1; col++) { @@ -1887,9 +1891,9 @@ void ColumnArea::mousePressEvent(QMouseEvent *event) { // synchronize the current column and the current fx TApp::instance()->getCurrentFx()->setFx(column->getFx()); } else if (m_col >= 0) { - if (m_viewer->getColumnSelection()->isColumnSelected(m_col) && - event->button() == Qt::RightButton) - return; + if (m_viewer->getColumnSelection()->isColumnSelected(m_col) && + event->button() == Qt::RightButton) + return; setDragTool(XsheetGUI::DragTool::makeColumnSelectionTool(m_viewer)); TApp::instance()->getCurrentFx()->setFx(0); } @@ -2199,6 +2203,7 @@ void ColumnArea::contextMenuEvent(QContextMenuEvent *event) { menu.addSeparator(); menu.addAction(cmdManager->getAction(MI_InsertFx)); menu.addAction(cmdManager->getAction(MI_NewNoteLevel)); + menu.addAction(cmdManager->getAction(MI_RemoveEmptyColumns)); menu.addSeparator(); if (m_viewer->getXsheet()->isColumnEmpty(col) || (cell.m_level && cell.m_level->getChildLevel())) diff --git a/toonz/sources/toonz/xsheetcmd.cpp b/toonz/sources/toonz/xsheetcmd.cpp index 9fa7306..1aa3480 100644 --- a/toonz/sources/toonz/xsheetcmd.cpp +++ b/toonz/sources/toonz/xsheetcmd.cpp @@ -59,6 +59,7 @@ #include "tapp.h" #include "duplicatepopup.h" #include "menubarcommandids.h" +#include "columncommand.h" // Qt includes #include <QClipboard> @@ -1002,6 +1003,9 @@ static void newNoteLevel() { obj->setName(str.toStdString()); TUndoManager::manager()->add(new NewNoteLevelUndo(textSoundCol, col, str)); + + TXsheetHandle *xshHandle = app->getCurrentXsheet(); + xshHandle->notifyXsheetChanged(); } //============================================================ @@ -1014,6 +1018,29 @@ public: //============================================================ +static void removeEmptyColumns() { + TTool::Application *app = TTool::getApplication(); + TXsheet *xsh = app->getCurrentScene()->getScene()->getXsheet(); + std::set<int> indices; + + for (int i = 0; i < xsh->getColumnCount(); i++) { + TXshColumn *column = xsh->getColumn(i); + if (!column || column->isEmpty()) indices.insert(i); + } + + if (indices.size()) ColumnCmd::deleteColumns(indices, false, false); + + app->getCurrentXsheet()->notifyXsheetChanged(); +} + +class RemoveEmptyColumnsCommand final : public MenuItemHandler { +public: + RemoveEmptyColumnsCommand() : MenuItemHandler(MI_RemoveEmptyColumns) {} + void execute() override { XshCmd::removeEmptyColumns(); } +} RemoveEmptyColumnsCommand; + +//============================================================ + } // namespace XshCmd //***************************************************************************** diff --git a/toonz/sources/toonz/xsheetdragtool.cpp b/toonz/sources/toonz/xsheetdragtool.cpp index fe52e20..cfc11f2 100644 --- a/toonz/sources/toonz/xsheetdragtool.cpp +++ b/toonz/sources/toonz/xsheetdragtool.cpp @@ -5,6 +5,7 @@ // Tnz6 includes #include "xsheetviewer.h" #include "cellselection.h" +#include "columncommand.h" #include "keyframeselection.h" #include "cellkeyframeselection.h" #include "tapp.h" @@ -1574,14 +1575,15 @@ public: //----------------------------------------------------------------------------- class ColumnMoveDragTool final : public XsheetGUI::DragTool { - int m_offset, m_firstCol, m_lastCol; + int m_offset, m_firstCol, m_lastCol, m_origOffset; public: ColumnMoveDragTool(XsheetViewer *viewer) : XsheetGUI::DragTool(viewer) , m_firstCol(-1) , m_lastCol(-1) - , m_offset(0) {} + , m_offset(0) + , m_origOffset(0) {} void onClick(const CellPosition &pos) override { int col = pos.layer(); @@ -1595,22 +1597,62 @@ public: if (indices.empty()) return; m_firstCol = m_lastCol = *indices.begin(); assert(m_firstCol >= 0); - m_offset = m_firstCol - col; + m_origOffset = m_offset = m_firstCol - col; assert(m_lastCol == *indices.begin()); getViewer()->update(); + + if (!getViewer()->orientation()->isVerticalTimeline()) + TUndoManager::manager()->beginBlock(); } void onDrag(const CellPosition &pos) override { int col = pos.layer(); TColumnSelection *selection = getViewer()->getColumnSelection(); - std::set<int> indices = selection->getIndices(); + TApp *app = TApp::instance(); + TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); + + std::set<int> indices = selection->getIndices(); if (indices.empty()) return; assert(m_lastCol == *indices.begin()); + int origCol = col; if (col < 0) col = 0; - if (col == m_lastCol) return; - int dCol = col - m_lastCol; - m_lastCol = col; + int dCol = col - (m_lastCol - m_offset); + + int newBegin = *indices.begin() + dCol; + if (!getViewer()->orientation()->isVerticalTimeline()) { + if (origCol < 0) { + dCol += origCol; + newBegin = *indices.begin() + dCol; + } + std::set<int> ii; + if (newBegin < 0) { + newBegin *= -1; + for (int x = 0; x < newBegin; x++) ii.insert(x); + ColumnCmd::insertEmptyColumns(ii); + selection->selectNone(); + for (std::set<int>::const_iterator it = indices.begin(); + it != indices.end(); it++) + selection->selectColumn(*it + newBegin, true); + indices = selection->getIndices(); + col = origCol + newBegin; + m_lastCol += newBegin; + m_firstCol += newBegin; + int currentIndx = app->getCurrentColumn()->getColumnIndex(); + app->getCurrentColumn()->setColumnIndex(currentIndx + newBegin); + } else { + int currEnd = xsh->getColumnCount() - 1; + int newEnd = *indices.rbegin() + dCol; + if (newEnd > currEnd) { + for (int x = currEnd + 1; x <= newEnd; x++) ii.insert(x); + ColumnCmd::insertEmptyColumns(ii); + } + } + } else if (newBegin < 0) + return; + + if (col == (m_lastCol - m_offset)) return; + m_lastCol = col + m_offset; assert(*indices.begin() + dCol >= 0); @@ -1623,14 +1665,18 @@ public: } void onRelease(const CellPosition &pos) override { int delta = m_lastCol - m_firstCol; - if (delta == 0) return; - TColumnSelection *selection = getViewer()->getColumnSelection(); - std::set<int> indices = selection->getIndices(); - if (!indices.empty()) { - TUndoManager::manager()->add(new ColumnMoveUndo(indices, delta)); - TApp::instance()->getCurrentScene()->setDirtyFlag(true); - TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); + if (delta != 0) { + TColumnSelection *selection = getViewer()->getColumnSelection(); + std::set<int> indices = selection->getIndices(); + if (!indices.empty()) { + TUndoManager::manager()->add(new ColumnMoveUndo(indices, delta)); + TApp::instance()->getCurrentScene()->setDirtyFlag(true); + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); + } } + + if (!getViewer()->orientation()->isVerticalTimeline()) + TUndoManager::manager()->endBlock(); } }; @@ -2019,6 +2065,7 @@ public: refreshCellsArea(); } void drawCellsArea(QPainter &p) override { + const Orientation *o = getViewer()->orientation(); CellPosition beginDragPosition = getViewer()->xyToPosition(m_curPos); TPoint pos(beginDragPosition.layer(), beginDragPosition.frame()); // row and cell coordinates @@ -2028,9 +2075,17 @@ public: if (rect.x1 < 0 || rect.y1 < 0) return; if (rect.x0 < 0) rect.x0 = 0; if (rect.y0 < 0) rect.y0 = 0; - QRect screenCell = getViewer()->rangeToXYRect( - CellRange(CellPosition(rect.y0, rect.x0), - CellPosition(rect.y1 + 1, rect.x1 + 1))); + QRect screenCell; + if (o->isVerticalTimeline()) + screenCell = getViewer()->rangeToXYRect( + CellRange(CellPosition(rect.y0, rect.x0), + CellPosition(rect.y1 + 1, rect.x1 + 1))); + else { + int newY0 = qMax(rect.y0, rect.y1); + int newY1 = qMin(rect.y0, rect.y1); + screenCell = getViewer()->rangeToXYRect(CellRange( + CellPosition(rect.x0, newY0), CellPosition(rect.x1 + 1, newY1 - 1))); + } p.setPen(m_valid ? QColor(190, 220, 255) : QColor(255, 0, 0)); int i; for (i = 0; i < 3; i++) // thick border within cell diff --git a/toonz/sources/toonz/xsheetviewer.cpp b/toonz/sources/toonz/xsheetviewer.cpp index ba18fb7..f7b1e67 100644 --- a/toonz/sources/toonz/xsheetviewer.cpp +++ b/toonz/sources/toonz/xsheetviewer.cpp @@ -667,14 +667,25 @@ bool XsheetViewer::refreshContentSize(int dx, int dy) { TXsheet *xsh = getXsheet(); int frameCount = xsh ? xsh->getFrameCount() : 0; int columnCount = xsh ? xsh->getColumnCount() : 0; - QPoint contentSize = - positionToXY(CellPosition(frameCount + 1, columnCount + 1)); + QPoint contentSize; + + if (m_orientation->isVerticalTimeline()) + contentSize = positionToXY(CellPosition(frameCount + 1, columnCount + 1)); + else { + contentSize = positionToXY(CellPosition(frameCount + 1, 0)); + + ColumnFan *fan = xsh->getColumnFan(m_orientation); + contentSize.setY(contentSize.y() + (fan->isActive(0) + ? m_orientation->cellHeight() + : m_orientation->foldedCellSize())); + } QSize actualSize(contentSize.x(), contentSize.y()); int x = viewportSize.width() - offset.x(); // wtf is going on int y = viewportSize.height() - offset.y(); if (x > actualSize.width()) actualSize.setWidth(x); - if (y > actualSize.height()) actualSize.setHeight(y); + if (m_orientation->isVerticalTimeline() && y > actualSize.height()) + actualSize.setHeight(y); if (actualSize == m_cellArea->size()) return false; @@ -707,11 +718,23 @@ void XsheetViewer::updateAreeSize() { QPoint areaFilled(0, 0); TXsheet *xsh = getXsheet(); - if (xsh) - areaFilled = positionToXY( - CellPosition(xsh->getFrameCount() + 1, xsh->getColumnCount() + 1)); + if (xsh) { + if (o->isVerticalTimeline()) + areaFilled = positionToXY( + CellPosition(xsh->getFrameCount() + 1, xsh->getColumnCount() + 1)); + else { + areaFilled = positionToXY(CellPosition(xsh->getFrameCount() + 1, 0)); + + ColumnFan *fan = xsh->getColumnFan(m_orientation); + areaFilled.setY(areaFilled.y() + (fan->isActive(0) + ? o->cellHeight() + : o->foldedCellSize())); + } + } if (viewArea.right() < areaFilled.x()) viewArea.setRight(areaFilled.x()); - if (viewArea.bottom() < areaFilled.y()) viewArea.setBottom(areaFilled.y()); + if (viewArea.bottom() < areaFilled.y() || + (!o->isVerticalTimeline() && viewArea.bottom() != areaFilled.y())) + viewArea.setBottom(areaFilled.y()); NumberRange allLayer = o->layerSide(viewArea); NumberRange allFrame = o->frameSide(viewArea); @@ -725,12 +748,51 @@ void XsheetViewer::updateAreeSize() { //----------------------------------------------------------------------------- +int XsheetViewer::colToTimelineLayerAxis(int layer) const { + const Orientation *o = orientation(); + TXsheet *xsh = getXsheet(); + if (!xsh) return 0; + ColumnFan *fan = xsh->getColumnFan(o); + + int yBottom = o->colToLayerAxis(layer, fan) + + (fan->isActive(layer) ? o->cellHeight() : o->foldedCellSize()) - + 1; + int columnCount = qMax(1, xsh->getColumnCount()); + int layerHeightActual = o->colToLayerAxis(columnCount, fan) - 1; + + return layerHeightActual - yBottom; +} + +//----------------------------------------------------------------------------- + CellPosition XsheetViewer::xyToPosition(const QPoint &point) const { const Orientation *o = orientation(); QPoint usePoint = point; + TXsheet *xsh = getXsheet(); + + if (!xsh) return CellPosition(0, 0); + + ColumnFan *fan = xsh->getColumnFan(o); + if (!o->isVerticalTimeline()) usePoint.setX((usePoint.x() * 100) / getFrameZoomFactor()); - return o->xyToPosition(usePoint, getXsheet()->getColumnFan(o)); + + if (o->isVerticalTimeline()) return o->xyToPosition(usePoint, fan); + + // For timeline mode, we need to base the Y axis on the bottom of the column + // area + // since the layers are flipped + int columnCount = qMax(1, xsh->getColumnCount()); + int colAreaHeight = o->colToLayerAxis(columnCount, fan); + + usePoint.setY(colAreaHeight - usePoint.y()); + + CellPosition resultCP = o->xyToPosition(usePoint, fan); + if (point.y() > colAreaHeight) { + int colsBelow = ((point.y() - colAreaHeight) / o->cellHeight()) + 1; + resultCP.setLayer(-colsBelow); + } + return resultCP; } CellPosition XsheetViewer::xyToPosition(const TPoint &point) const { return xyToPosition(QPoint(point.x, point.y)); @@ -743,15 +805,42 @@ CellPosition XsheetViewer::xyToPosition(const TPointD &point) const { QPoint XsheetViewer::positionToXY(const CellPosition &pos) const { const Orientation *o = orientation(); - QPoint result = o->positionToXY(pos, getXsheet()->getColumnFan(o)); + TXsheet *xsh = getXsheet(); + if (!xsh) return QPoint(0, 0); + ColumnFan *fan = xsh->getColumnFan(o); + QPoint usePoint = o->positionToXY(pos, fan); + if (!o->isVerticalTimeline()) - result.setX((result.x() * getFrameZoomFactor()) / 100); - return result; + usePoint.setX((usePoint.x() * getFrameZoomFactor()) / 100); + + if (o->isVerticalTimeline()) return usePoint; + + // For timeline mode, we need to base the Y axis on the bottom of the column + // area + // since the layers are flipped + + usePoint.setY(usePoint.y() + (fan->isActive(pos.layer()) + ? o->cellHeight() + : o->foldedCellSize())); + int columnCount = qMax(1, xsh->getColumnCount()); + int colsHeight = o->colToLayerAxis(columnCount, fan); + + if (colsHeight) + usePoint.setY(colsHeight - usePoint.y()); + else + usePoint.setY(0); + + return usePoint; } int XsheetViewer::columnToLayerAxis(int layer) const { const Orientation *o = orientation(); - return o->colToLayerAxis(layer, getXsheet()->getColumnFan(o)); + TXsheet *xsh = getXsheet(); + if (!xsh) return 0; + if (o->isVerticalTimeline()) + return o->colToLayerAxis(layer, xsh->getColumnFan(o)); + else + return colToTimelineLayerAxis(layer); } int XsheetViewer::rowToFrameAxis(int frame) const { int result = orientation()->rowToFrameAxis(frame); @@ -1091,13 +1180,19 @@ void XsheetViewer::keyPressEvent(QKeyEvent *event) { struct Locals { XsheetViewer *m_this; - void scrollTo(double y, const QRect &visibleRect) { + void scrollVertTo(double y, const QRect &visibleRect) { int deltaY = (y < visibleRect.top()) ? y - visibleRect.top() : y - visibleRect.bottom(); m_this->scroll(QPoint(0, deltaY)); } + void scrollHorizTo(double x, const QRect &visibleRect) { + int deltaX = (x < visibleRect.left()) ? x - visibleRect.left() + : x - visibleRect.right(); + + m_this->scroll(QPoint(deltaX, 0)); + } } locals = {this}; if (changeFrameSkippingHolds(event)) return; @@ -1157,21 +1252,29 @@ void XsheetViewer::keyPressEvent(QKeyEvent *event) { switch (key) { case Qt::Key_PageUp: - locals.scrollTo( + locals.scrollVertTo( visibleRect.top() - visibleRowCount * orientation()->cellHeight(), visibleRect); break; case Qt::Key_PageDown: - locals.scrollTo( + locals.scrollVertTo( visibleRect.bottom() + visibleRowCount * orientation()->cellHeight(), visibleRect); break; case Qt::Key_Home: - locals.scrollTo(0, visibleRect); + if (orientation()->isVerticalTimeline()) + locals.scrollVertTo(0, visibleRect); + else + locals.scrollHorizTo(0, visibleRect); + break; case Qt::Key_End: - locals.scrollTo((frameCount + 1) * orientation()->cellHeight(), - visibleRect); + if (orientation()->isVerticalTimeline()) + locals.scrollVertTo((frameCount + 1) * orientation()->cellHeight(), + visibleRect); + else + locals.scrollHorizTo((frameCount + 1) * orientation()->cellWidth(), + visibleRect); break; } break; @@ -1191,6 +1294,8 @@ void XsheetViewer::keyReleaseEvent(QKeyEvent *event) { void XsheetViewer::enterEvent(QEvent *) { m_cellArea->onControlPressed(false); m_columnArea->onControlPressed(false); + TApp *app = TApp::instance(); + app->setCurrentXsheetViewer(this); } //----------------------------------------------------------------------------- @@ -1282,8 +1387,10 @@ void XsheetViewer::onCurrentColumnSwitched() { //----------------------------------------------------------------------------- void XsheetViewer::scrollToColumn(int col) { - int x0 = columnToLayerAxis(col); - int x1 = columnToLayerAxis(col + 1); + int colNext = col + (m_orientation->isVerticalTimeline() ? 1 : -1); + if (colNext < 0) colNext = 0; + int x0 = columnToLayerAxis(col); + int x1 = columnToLayerAxis(colNext); if (orientation()->isVerticalTimeline()) scrollToHorizontalRange(x0, x1); diff --git a/toonz/sources/toonz/xsheetviewer.h b/toonz/sources/toonz/xsheetviewer.h index 65cff19..cee9002 100644 --- a/toonz/sources/toonz/xsheetviewer.h +++ b/toonz/sources/toonz/xsheetviewer.h @@ -618,6 +618,8 @@ public: CellPosition xyToPosition(const TPointD &point) const; QPoint positionToXY(const CellPosition &pos) const; + int colToTimelineLayerAxis(int layer) const; + int columnToLayerAxis(int layer) const; int rowToFrameAxis(int frame) const; diff --git a/toonz/sources/toonz/xshrowviewer.cpp b/toonz/sources/toonz/xshrowviewer.cpp index 73c9e95..1eaa75c 100644 --- a/toonz/sources/toonz/xshrowviewer.cpp +++ b/toonz/sources/toonz/xshrowviewer.cpp @@ -133,6 +133,7 @@ void RowArea::drawRows(QPainter &p, int r0, int r1) { if (!o->isVerticalTimeline() && m_viewer->getFrameZoomFactor() <= 50) { QPoint basePoint = m_viewer->positionToXY(CellPosition(r, 0)); + if (!o->isVerticalTimeline()) basePoint.setY(0); QRect indRect = o->rect(PredefinedRect::FRAME_INDICATOR).translated(basePoint); indRect.adjust(-frameAdj / 2, 0, -frameAdj / 2, 0); @@ -161,11 +162,13 @@ void RowArea::drawRows(QPainter &p, int r0, int r1) { p.setPen(m_viewer->getTextColor()); QPoint basePoint = m_viewer->positionToXY(CellPosition(r, 0)); - QRect labelRect = - o->rect(PredefinedRect::FRAME_LABEL).translated(basePoint); + if (!m_viewer->orientation()->isVerticalTimeline()) basePoint.setY(0); + QRect labelRect = m_viewer->orientation() + ->rect(PredefinedRect::FRAME_LABEL) + .translated(basePoint); labelRect.adjust(-frameAdj / 2, 0, -frameAdj / 2, 0); - - int align = o->dimension(PredefinedDimension::FRAME_LABEL_ALIGN); + int align = m_viewer->orientation()->dimension( + PredefinedDimension::FRAME_LABEL_ALIGN); // display time and/or frame number z++; switch (m_viewer->getFrameDisplayStyle()) { @@ -276,6 +279,7 @@ void RowArea::drawRows(QPainter &p, int r0, int r1) { void RowArea::drawPlayRange(QPainter &p, int r0, int r1) { bool playRangeEnabled = XsheetGUI::isPlayRangeEnabled(); int frameAdj = m_viewer->getFrameZoomAdjustment(); + TXsheet *xsh = m_viewer->getXsheet(); // Update the play range internal fields if (playRangeEnabled) { @@ -285,8 +289,7 @@ void RowArea::drawPlayRange(QPainter &p, int r0, int r1) { // if the preview range is not set, then put markers at the first and the last // frames of the scene else { - TXsheet *xsh = m_viewer->getXsheet(); - m_r1 = xsh->getFrameCount() - 1; + m_r1 = xsh->getFrameCount() - 1; if (m_r1 == -1) return; m_r0 = 0; } @@ -294,8 +297,11 @@ void RowArea::drawPlayRange(QPainter &p, int r0, int r1) { QColor ArrowColor = (playRangeEnabled) ? QColor(255, 255, 255) : grey150; p.setBrush(QBrush(ArrowColor)); + int topOrLeftCol = + m_viewer->orientation()->isVerticalTimeline() ? 0 : xsh->getColumnCount(); if (m_r0 > r0 - 1 && r1 + 1 > m_r0) { QPoint topLeft = m_viewer->positionToXY(CellPosition(m_r0, 0)); + if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); m_viewer->drawPredefinedPath(p, PredefinedPath::BEGIN_PLAY_RANGE, topLeft, ArrowColor, QColor(Qt::black)); } @@ -303,6 +309,7 @@ void RowArea::drawPlayRange(QPainter &p, int r0, int r1) { if (m_r1 > r0 - 1 && r1 + 1 > m_r1) { QPoint topLeft = m_viewer->positionToXY(CellPosition(m_r1, 0)); topLeft.setX(topLeft.x() - frameAdj); + if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); m_viewer->drawPredefinedPath(p, PredefinedPath::END_PLAY_RANGE, topLeft, ArrowColor, QColor(Qt::black)); } @@ -315,7 +322,8 @@ void RowArea::drawCurrentRowGadget(QPainter &p, int r0, int r1) { if (currentRow < r0 || r1 < currentRow) return; QPoint topLeft = m_viewer->positionToXY(CellPosition(currentRow, 0)); - QRect header = m_viewer->orientation() + if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); + QRect header = m_viewer->orientation() ->rect(PredefinedRect::FRAME_HEADER) .translated(topLeft); int frameAdj = m_viewer->getFrameZoomAdjustment(); @@ -405,7 +413,8 @@ void RowArea::drawOnionSkinSelection(QPainter &p) { } // Draw onion skin main handle QPoint handleTopLeft = m_viewer->positionToXY(CellPosition(currentRow, 0)); - QRect handleRect = onionRect.translated(handleTopLeft); + if (!m_viewer->orientation()->isVerticalTimeline()) handleTopLeft.setY(0); + QRect handleRect = onionRect.translated(handleTopLeft); handleRect.adjust(-frameAdj / 2, 0, -frameAdj / 2, 0); int angle180 = 16 * 180; int turn = @@ -428,7 +437,8 @@ void RowArea::drawOnionSkinSelection(QPainter &p) { else p.setBrush(Qt::NoBrush); QPoint topLeft = m_viewer->positionToXY(CellPosition(currentRow + mos, 0)); - QRect dotRect = m_viewer->orientation() + if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); + QRect dotRect = m_viewer->orientation() ->rect(PredefinedRect::ONION_DOT) .translated(topLeft); dotRect.adjust(-frameAdj / 2, 0, -frameAdj / 2, 0); @@ -447,7 +457,8 @@ void RowArea::drawOnionSkinSelection(QPainter &p) { else p.setBrush(Qt::NoBrush); QPoint topLeft = m_viewer->positionToXY(CellPosition(fos, 0)); - QRect dotRect = m_viewer->orientation() + if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); + QRect dotRect = m_viewer->orientation() ->rect(PredefinedRect::ONION_DOT_FIXED) .translated(topLeft); dotRect.adjust(-frameAdj / 2, 0, -frameAdj / 2, 0); @@ -459,6 +470,7 @@ void RowArea::drawOnionSkinSelection(QPainter &p) { p.setPen(QColor(255, 128, 0)); p.setBrush(QBrush(QColor(255, 255, 0))); QPoint topLeft = m_viewer->positionToXY(CellPosition(m_row, 0)); + if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); QRect dotRect = m_viewer->orientation() ->rect(m_showOnionToSet == Fos ? PredefinedRect::ONION_DOT_FIXED @@ -476,7 +488,8 @@ void RowArea::drawCurrentTimeIndicator(QPainter &p) { int currentRow = m_viewer->getCurrentRow(); QPoint topLeft = m_viewer->positionToXY(CellPosition(currentRow, 0)); - QRect header = m_viewer->orientation() + if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); + QRect header = m_viewer->orientation() ->rect(PredefinedRect::FRAME_HEADER) .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) .translated(topLeft); @@ -499,7 +512,8 @@ void RowArea::drawCurrentTimeLine(QPainter &p) { int currentRow = m_viewer->getCurrentRow(); QPoint topLeft = m_viewer->positionToXY(CellPosition(currentRow, 0)); - QRect header = m_viewer->orientation() + if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); + QRect header = m_viewer->orientation() ->rect(PredefinedRect::FRAME_HEADER) .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) .translated(topLeft); @@ -570,13 +584,14 @@ void RowArea::drawPinnedCenterKeys(QPainter &p, int r0, int r1) { if (tmp_pinnedCol != prev_pinnedCol) { prev_pinnedCol = tmp_pinnedCol; if (r != r0 - 1) { - QPoint mouseInCell = m_pos - m_viewer->positionToXY(CellPosition(r, 0)); + QPoint topLeft = m_viewer->positionToXY(CellPosition(r, 0)); + if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); + QPoint mouseInCell = m_pos - topLeft; if (keyRect.contains(mouseInCell)) p.setBrush(QColor(30, 210, 255)); else p.setBrush(QColor(0, 175, 255)); - QPoint topLeft = m_viewer->positionToXY(CellPosition(r, 0)); QRect adjusted = keyRect.translated(topLeft); p.drawRect(adjusted); @@ -614,6 +629,11 @@ void RowArea::paintEvent(QPaintEvent *event) { // current frame drawCurrentRowGadget(p, r0, r1); + if (TApp::instance()->getCurrentFrame()->isEditingScene() && + Preferences::instance()->isCurrentTimelineIndicatorEnabled() && + !m_viewer->orientation()->isVerticalTimeline()) + drawCurrentTimeLine(p); + drawRows(p, r0, r1); if (TApp::instance()->getCurrentFrame()->isEditingScene()) { @@ -622,14 +642,8 @@ void RowArea::paintEvent(QPaintEvent *event) { else if (Preferences::instance()->isCurrentTimelineIndicatorEnabled() && !m_viewer->orientation()->isVerticalTimeline()) drawCurrentTimeIndicator(p); - - if (Preferences::instance()->isCurrentTimelineIndicatorEnabled() && - !m_viewer->orientation()->isVerticalTimeline()) - drawCurrentTimeLine(p); } - // drawRows(p, r0, r1); - if (TApp::instance()->getCurrentTool()->getTool()->getName() == T_Skeleton) drawPinnedCenterKeys(p, r0, r1); @@ -656,8 +670,9 @@ void RowArea::mousePressEvent(QMouseEvent *event) { TPoint pos(event->pos().x(), event->pos().y()); int currentFrame = TApp::instance()->getCurrentFrame()->getFrame(); - int row = m_viewer->xyToPosition(pos).frame(); - QPoint topLeft = m_viewer->positionToXY(CellPosition(row, 0)); + int row = m_viewer->xyToPosition(pos).frame(); + QPoint topLeft = m_viewer->positionToXY(CellPosition(row, 0)); + if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); QPoint mouseInCell = event->pos() - topLeft; int frameAdj = m_viewer->getFrameZoomAdjustment(); @@ -779,8 +794,9 @@ void RowArea::mouseMoveEvent(QMouseEvent *event) { int currentRow = TApp::instance()->getCurrentFrame()->getFrame(); int row = m_viewer->xyToPosition(m_pos).frame(); int frameAdj = m_viewer->getFrameZoomAdjustment(); - QPoint mouseInCell = - event->pos() - m_viewer->positionToXY(CellPosition(row, 0)); + QPoint topLeft = m_viewer->positionToXY(CellPosition(row, 0)); + if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); + QPoint mouseInCell = event->pos() - topLeft; if (row < 0) return; // whether to show ability to set onion marks if (Preferences::instance()->isOnionSkinEnabled() && row != currentRow) { @@ -800,7 +816,7 @@ void RowArea::mouseMoveEvent(QMouseEvent *event) { int pinnedCenterColumnId = -1; if (TApp::instance()->getCurrentTool()->getTool()->getName() == T_Skeleton && o->rect(PredefinedRect::PINNED_CENTER_KEY) - .adjusted(-frameAdj, 0, -frameAdj, 0) + .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) .contains(mouseInCell)) { int col = m_viewer->getCurrentColumn(); TXsheet *xsh = m_viewer->getXsheet(); @@ -825,7 +841,9 @@ void RowArea::mouseMoveEvent(QMouseEvent *event) { update(); QPoint base0 = m_viewer->positionToXY(CellPosition(m_r0, 0)); + if (!m_viewer->orientation()->isVerticalTimeline()) base0.setY(0); QPoint base1 = m_viewer->positionToXY(CellPosition(m_r1, 0)); + if (!m_viewer->orientation()->isVerticalTimeline()) base1.setY(0); QPainterPath startArrow = o->path(PredefinedPath::BEGIN_PLAY_RANGE).translated(base0); QPainterPath endArrow = @@ -841,7 +859,9 @@ void RowArea::mouseMoveEvent(QMouseEvent *event) { .arg((isRootBonePinned) ? " (Root)" : ""); else if (row == currentRow) { if (Preferences::instance()->isOnionSkinEnabled() && - o->rect(PredefinedRect::ONION).contains(mouseInCell)) + o->rect(PredefinedRect::ONION) + .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) + .contains(mouseInCell)) m_tooltip = tr("Double Click to Toggle Onion Skin"); else m_tooltip = tr("Current Frame"); @@ -952,13 +972,16 @@ int RowArea::getNonEmptyCell(int row, int column, Direction direction) { void RowArea::mouseDoubleClickEvent(QMouseEvent *event) { int currentFrame = TApp::instance()->getCurrentFrame()->getFrame(); int row = m_viewer->xyToPosition(event->pos()).frame(); - QPoint mouseInCell = - event->pos() - m_viewer->positionToXY(CellPosition(row, 0)); + int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint topLeft = m_viewer->positionToXY(CellPosition(row, 0)); + if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); + QPoint mouseInCell = event->pos() - topLeft; if (TApp::instance()->getCurrentFrame()->isEditingScene() && event->buttons() & Qt::LeftButton && Preferences::instance()->isOnionSkinEnabled() && row == currentFrame && m_viewer->orientation() ->rect(PredefinedRect::ONION) + .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) .contains(mouseInCell)) { TOnionSkinMaskHandle *osmh = TApp::instance()->getCurrentOnionSkin(); OnionSkinMask osm = osmh->getOnionSkinMask(); diff --git a/toonz/sources/toonzlib/orientation.cpp b/toonz/sources/toonzlib/orientation.cpp index 0e9b386..6c3ab0a 100644 --- a/toonz/sources/toonzlib/orientation.cpp +++ b/toonz/sources/toonzlib/orientation.cpp @@ -19,6 +19,7 @@ const int ONION_DOT_SIZE = 8; const int PINNED_SIZE = 10; const int FRAME_DOT_SIZE = 8; const int FRAME_IND_SIZE = 3; +const int FOLDED_CELL_SIZE = 9; } class TopToBottomOrientation : public Orientation { @@ -73,6 +74,7 @@ public: virtual int cellWidth() const override { return CELL_WIDTH; } virtual int cellHeight() const override { return CELL_HEIGHT; } + virtual int foldedCellSize() const override { return FOLDED_CELL_SIZE; } }; class LeftToRightOrientation : public Orientation { @@ -132,6 +134,7 @@ public: virtual int cellWidth() const override { return CELL_WIDTH; } virtual int cellHeight() const override { return CELL_HEIGHT; } + virtual int foldedCellSize() const override { return FOLDED_CELL_SIZE; } }; /// ------------------------------------------------------------------------------- @@ -1167,9 +1170,9 @@ QPoint LeftToRightOrientation::topRightCorner(const QRect &area) const { CellPosition LeftToRightOrientation::arrowShift(int direction) const { switch (direction) { case Qt::Key_Up: - return CellPosition(0, -1); - case Qt::Key_Down: return CellPosition(0, 1); + case Qt::Key_Down: + return CellPosition(0, -1); case Qt::Key_Left: return CellPosition(-1, 0); case Qt::Key_Right: