Merge pull request #847 from manongjohn/implicit_holds
Implicit Frame Hold
This commit is contained in:
commit
6f1d0fc0b6
52 changed files with 1185 additions and 265 deletions
|
@ -2283,6 +2283,7 @@ XsheetViewer {
|
|||
qproperty-LightBGColor: #d8d8d8;
|
||||
qproperty-DarkBGColor: #c9c9c9;
|
||||
qproperty-DarkLineColor: #7e7e7e;
|
||||
qproperty-ImplicitCellAlpha: 60;
|
||||
qproperty-TimelineIconLineColor: rgba(0, 0, 0, 0.4);
|
||||
qproperty-XsheetColumnNameBgColor: rgba(0, 0, 0, 0);
|
||||
qproperty-XsheetDragBarHighlightColor: rgba(255, 255, 255, 0.15);
|
||||
|
|
|
@ -2283,6 +2283,7 @@ XsheetViewer {
|
|||
qproperty-LightBGColor: #c8c8c8;
|
||||
qproperty-DarkBGColor: #b9b9b9;
|
||||
qproperty-DarkLineColor: #6e6e6e;
|
||||
qproperty-ImplicitCellAlpha: 60;
|
||||
qproperty-TimelineIconLineColor: rgba(0, 0, 0, 0.3);
|
||||
qproperty-XsheetColumnNameBgColor: rgba(0, 0, 0, 0);
|
||||
qproperty-XsheetDragBarHighlightColor: rgba(255, 255, 255, 0.15);
|
||||
|
|
|
@ -2283,6 +2283,7 @@ XsheetViewer {
|
|||
qproperty-LightBGColor: #ffffff;
|
||||
qproperty-DarkBGColor: #ffffff;
|
||||
qproperty-DarkLineColor: #ffffff;
|
||||
qproperty-ImplicitCellAlpha: 115;
|
||||
qproperty-TimelineIconLineColor: rgba(0, 0, 0, 0.144);
|
||||
qproperty-XsheetColumnNameBgColor: rgba(0, 0, 0, 0);
|
||||
qproperty-XsheetDragBarHighlightColor: rgba(255, 255, 255, 0.15);
|
||||
|
|
|
@ -2283,6 +2283,7 @@ XsheetViewer {
|
|||
qproperty-LightBGColor: #f0f0f0;
|
||||
qproperty-DarkBGColor: #e1e1e1;
|
||||
qproperty-DarkLineColor: #969696;
|
||||
qproperty-ImplicitCellAlpha: 60;
|
||||
qproperty-TimelineIconLineColor: rgba(0, 0, 0, 0.3);
|
||||
qproperty-XsheetColumnNameBgColor: rgba(0, 0, 0, 0);
|
||||
qproperty-XsheetDragBarHighlightColor: rgba(255, 255, 255, 0.15);
|
||||
|
|
|
@ -423,6 +423,8 @@
|
|||
@cellHighlightTintColor: @hl-bg-color;
|
||||
@cellHighlightTintAmount: 77;
|
||||
|
||||
@xsheet-ImplicitCellAlpha: 60;
|
||||
|
||||
@xsheet-EmptyCell-color: @xsheet-OnionSkinAreaBG-color;
|
||||
@xsheet-NotEmptyColumn-color: darken(@bg, 3);
|
||||
@xsheet-SelectedEmptyCell-color: fade(mix(lighten(@xsheet-EmptyCell-color, 20), @cellHighlightTintColor, 80), 50);
|
||||
|
|
|
@ -153,6 +153,8 @@ XsheetViewer {
|
|||
qproperty-DarkBGColor: @xsheet-DarkBG-color;
|
||||
qproperty-DarkLineColor: @xsheet-DarkLine-color;
|
||||
|
||||
qproperty-ImplicitCellAlpha: @xsheet-ImplicitCellAlpha;
|
||||
|
||||
// Column Header: Vertical
|
||||
qproperty-TimelineIconLineColor: @timeline-IconLine-color;
|
||||
qproperty-XsheetColumnNameBgColor: @xsheet-ColumnNameBg-color;
|
||||
|
|
|
@ -191,6 +191,8 @@
|
|||
@columnBorderDarkness: 15;
|
||||
@cellHighlightLightness: 10;
|
||||
|
||||
@xsheet-ImplicitCellAlpha: 115;
|
||||
|
||||
@xsheet-EmptyCell-color: @xsheet-OnionSkinAreaBG-color;
|
||||
@xsheet-NotEmptyColumn-color: @xsheet-bg-color;
|
||||
@xsheet-SelectedEmptyCell-color: fade(mix(lighten(@xsheet-EmptyCell-color, -20), @cellHighlightTintColor, 80), 50);
|
||||
|
|
|
@ -218,6 +218,8 @@
|
|||
@columnBorderDesaturation: 0;
|
||||
@columnBorderDarkness: 15;
|
||||
|
||||
@xsheet-ImplicitCellAlpha: 75;
|
||||
|
||||
@xsheet-LevelColumn-color: #78a578;
|
||||
@xsheet-VectorColumn-color: #a7637d;
|
||||
@xsheet-ChildColumn-color: #9a759c;
|
||||
|
|
|
@ -2283,6 +2283,7 @@ XsheetViewer {
|
|||
qproperty-LightBGColor: #ffffff;
|
||||
qproperty-DarkBGColor: #ffffff;
|
||||
qproperty-DarkLineColor: #cecece;
|
||||
qproperty-ImplicitCellAlpha: 75;
|
||||
qproperty-TimelineIconLineColor: rgba(0, 0, 0, 0.3);
|
||||
qproperty-XsheetColumnNameBgColor: rgba(0, 0, 0, 0);
|
||||
qproperty-XsheetDragBarHighlightColor: rgba(255, 255, 255, 0.15);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<command>MI_ToggleAutoCreate</command>
|
||||
<command>MI_ToggleCreationInHoldCells</command>
|
||||
<command>MI_ToggleAutoStretch</command>
|
||||
<command>MI_ToggleImplicitHold</command>
|
||||
<separator/>
|
||||
<command>MI_NewVectorLevel</command>
|
||||
<command>MI_NewToonzRasterLevel</command>
|
||||
|
|
|
@ -95,6 +95,8 @@ std::string TFrameId::expand(FrameFormat format) const {
|
|||
return "";
|
||||
else if (m_frame == NO_FRAME)
|
||||
return "-";
|
||||
else if (m_frame == STOP_FRAME)
|
||||
return "x";
|
||||
std::ostringstream o_buff;
|
||||
if (format == FOUR_ZEROS || format == UNDERSCORE_FOUR_ZEROS) {
|
||||
o_buff.fill('0');
|
||||
|
|
|
@ -36,7 +36,8 @@ class DVAPI TFrameId {
|
|||
public:
|
||||
enum {
|
||||
EMPTY_FRAME = -1, // es. pippo..tif
|
||||
NO_FRAME = -2 // es. pippo.tif
|
||||
NO_FRAME = -2, // es. pippo.tif
|
||||
STOP_FRAME = -3
|
||||
};
|
||||
|
||||
enum FrameFormat {
|
||||
|
@ -86,6 +87,7 @@ public:
|
|||
|
||||
bool isEmptyFrame() const { return m_frame == EMPTY_FRAME; }
|
||||
bool isNoFrame() const { return m_frame == NO_FRAME; }
|
||||
bool isStopFrame() const { return m_frame == STOP_FRAME; }
|
||||
|
||||
// operator string() const;
|
||||
std::string expand(FrameFormat format = FOUR_ZEROS) const;
|
||||
|
@ -280,6 +282,9 @@ type is a string that indicate the filename extension(ex:. bmp or .bmp)*/
|
|||
TFilePath withNoFrame() const {
|
||||
return withFrame(TFrameId(TFrameId::NO_FRAME));
|
||||
} // pippo.tif
|
||||
TFilePath withStopFrame() const {
|
||||
return withFrame(TFrameId(TFrameId::STOP_FRAME));
|
||||
}
|
||||
|
||||
TFilePath operator+(const TFilePath &fp) const;
|
||||
TFilePath &operator+=(const TFilePath &fp) /*{*this=*this+fp;return *this;}*/;
|
||||
|
|
|
@ -304,6 +304,9 @@ public:
|
|||
bool isAutoCreateEnabled() const { return getBoolValue(EnableAutocreation); }
|
||||
int getNumberingSystem() const { return getIntValue(NumberingSystem); }
|
||||
bool isAutoStretchEnabled() const { return getBoolValue(EnableAutoStretch); }
|
||||
bool isImplicitHoldEnabled() const {
|
||||
return getBoolValue(EnableImplicitHold);
|
||||
}
|
||||
bool isCreationInHoldCellsEnabled() const {
|
||||
return getBoolValue(EnableCreationInHoldCells);
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ enum PreferencesItemId {
|
|||
EnableAutocreation,
|
||||
NumberingSystem,
|
||||
EnableAutoStretch,
|
||||
EnableImplicitHold,
|
||||
EnableCreationInHoldCells,
|
||||
EnableAutoRenumber,
|
||||
vectorSnappingTarget,
|
||||
|
|
|
@ -141,7 +141,7 @@ Constructs a TXshColumn with default value.
|
|||
virtual TXshZeraryFxColumn *getZeraryFxColumn() { return 0; }
|
||||
virtual TXshMeshColumn *getMeshColumn() { return 0; }
|
||||
|
||||
virtual int getMaxFrame() const = 0;
|
||||
virtual int getMaxFrame(bool ignoreLastStop = false) const = 0;
|
||||
|
||||
virtual TXshColumn *clone() const = 0;
|
||||
|
||||
|
@ -219,7 +219,7 @@ If r0=r1=row return false.
|
|||
*/
|
||||
virtual bool getLevelRange(int row, int &r0, int &r1) const = 0;
|
||||
|
||||
virtual int getRange(int &r0, int &r1) const {
|
||||
virtual int getRange(int &r0, int &r1, bool ignoreLastStop = false) const {
|
||||
r0 = 0;
|
||||
r1 = -1;
|
||||
return 0;
|
||||
|
@ -330,7 +330,7 @@ Return not empty cell range. Set \b r0 and \b r1 to first
|
|||
and last row with not empty cell.
|
||||
\sa isEmpty() and getRowCount()
|
||||
*/
|
||||
int getRange(int &r0, int &r1) const override;
|
||||
int getRange(int &r0, int &r1, bool ignoreLastStop = false) const override;
|
||||
/*!
|
||||
Return row count.
|
||||
\sa isEmpty() and getRange()
|
||||
|
@ -386,7 +386,7 @@ Clear \b rowCount cells from line \b row, without shift.
|
|||
/*!
|
||||
Return last row with not empty cell.
|
||||
*/
|
||||
int getMaxFrame() const override;
|
||||
int getMaxFrame(bool ignoreLastStop = false) const override;
|
||||
|
||||
/*!
|
||||
Return first not empty row.
|
||||
|
|
|
@ -196,6 +196,10 @@ public:
|
|||
|
||||
const TXshCell &getCell(const CellPosition &pos) const;
|
||||
|
||||
bool isImplicitCell(int row, int col) const;
|
||||
|
||||
bool isImplicitCell(const CellPosition &pos) const;
|
||||
|
||||
bool setCell(int row, int col, const TXshCell &cell);
|
||||
/*! Set \b \e cells[] to \b \e rowCount cells of column identified by index \b
|
||||
\e col starting from row identified by index \b \e row. If column is empty
|
||||
|
|
|
@ -129,11 +129,11 @@ public:
|
|||
void saveData(TOStream &os) override;
|
||||
|
||||
/*! r0 : min row not empty, r1 : max row not empty. Return row count.*/
|
||||
int getRange(int &r0, int &r1) const override;
|
||||
int getRange(int &r0, int &r1, bool ignoreLastStop = false) const override;
|
||||
/*! Last not empty row - first not empty row. */
|
||||
int getRowCount() const override;
|
||||
/*! Return max row not empty. */
|
||||
int getMaxFrame() const override;
|
||||
int getMaxFrame(bool ignoreLastStop = false) const override;
|
||||
/*! Return min row not empty.*/
|
||||
int getFirstRow() const override;
|
||||
|
||||
|
|
|
@ -61,6 +61,17 @@ TPalette *getPalette(TXshColumn *column, int frame) {
|
|||
if (!cellColumn) return 0;
|
||||
|
||||
TXshCell cell = cellColumn->getCell(frame);
|
||||
// This is only relevant when Implicit Holds are enabled
|
||||
if (cell.isEmpty()) {
|
||||
int r0, r1;
|
||||
cellColumn->getRange(r0, r1);
|
||||
for (int r = std::min(r1, frame); r >= r0; r--) {
|
||||
cell = cellColumn->getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cell.isEmpty()) return 0;
|
||||
|
||||
TXshPaletteLevel *pl = cell.m_level->getPaletteLevel();
|
||||
|
|
|
@ -353,6 +353,11 @@ TImage *TTool::touchImage() {
|
|||
if (!xsh) return 0;
|
||||
|
||||
TXshCell cell = xsh->getCell(row, col);
|
||||
bool isImplicitCell = xsh->isImplicitCell(row, col);
|
||||
|
||||
// Stop frames cannot be modified
|
||||
if (cell.getFrameId().isStopFrame()) return 0;
|
||||
|
||||
TXshSimpleLevel *sl = cell.getSimpleLevel();
|
||||
|
||||
if (sl) {
|
||||
|
@ -380,7 +385,9 @@ TImage *TTool::touchImage() {
|
|||
// measure the hold length (starting from the current row) : r0-r1
|
||||
int r0 = row, r1 = row;
|
||||
if (isAutoStretchEnabled)
|
||||
while (xsh->getCell(r1 + 1, col) == cell) r1++;
|
||||
while (xsh->getCell(r1 + 1, col) == cell &&
|
||||
!xsh->isImplicitCell(r1 + 1, col))
|
||||
r1++;
|
||||
// find the proper frameid (possibly addisng suffix, in order to avoid a
|
||||
// fid already used)
|
||||
// find the proper frameid
|
||||
|
@ -418,7 +425,10 @@ TImage *TTool::touchImage() {
|
|||
currentXsheet->notifyXsheetChanged();
|
||||
currentScene->notifyCastChange();
|
||||
currentLevel->notifyLevelChange();
|
||||
m_cellsData.push_back({r0, r1, CellOps::ExistingToNew});
|
||||
if (isImplicitCell)
|
||||
m_cellsData.push_back({r0, r1, CellOps::BlankToNew});
|
||||
else
|
||||
m_cellsData.push_back({r0, r1, CellOps::ExistingToNew});
|
||||
}
|
||||
// if the level does not contain a frame in the current cell
|
||||
// (i.e. drawing on the cell with red numbers)
|
||||
|
@ -728,7 +738,8 @@ TFrameId TTool::getCurrentFid() const {
|
|||
int col = m_application->getCurrentColumn()->getColumnIndex();
|
||||
TXshCell cell =
|
||||
m_application->getCurrentXsheet()->getXsheet()->getCell(row, col);
|
||||
if (cell.isEmpty()) return TFrameId::NO_FRAME;
|
||||
if (cell.isEmpty() || cell.getFrameId().isStopFrame())
|
||||
return TFrameId::NO_FRAME;
|
||||
|
||||
return cell.getFrameId();
|
||||
}
|
||||
|
@ -1108,6 +1119,13 @@ QString TTool::updateEnabled(int rowIndex, int columnIndex) {
|
|||
"frames of a Single Frame level."));
|
||||
}
|
||||
}
|
||||
|
||||
// Stop frames cannot be modified
|
||||
if (xsh->getCell(rowIndex, columnIndex).getFrameId().isStopFrame()) {
|
||||
return (
|
||||
enable(false),
|
||||
QObject::tr("The current tool cannot be used on a stop frame."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -149,12 +149,25 @@ AutoInputCellNumberUndo::AutoInputCellNumberUndo(int increment, int interval,
|
|||
(m_r1 == -1) ? m_rowsCount - 1 : std::min(m_r1, m_r0 + m_rowsCount - 1);
|
||||
m_beforeCells.reset(
|
||||
new TXshCell[m_columnIndices.size() * (rowUpTo - m_r0 + 1)]);
|
||||
int k = 0;
|
||||
int k = 0;
|
||||
TXsheetP xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
|
||||
for (int c = 0; c < m_columnIndices.size(); ++c) {
|
||||
for (int r = m_r0; r <= rowUpTo; ++r)
|
||||
for (int r = m_r0; r <= rowUpTo; ++r) {
|
||||
const TXshCell &cell = xsh->getCell(r, m_columnIndices.at(c));
|
||||
m_beforeCells[k++] =
|
||||
TApp::instance()->getCurrentXsheet()->getXsheet()->getCell(
|
||||
r, m_columnIndices.at(c));
|
||||
xsh->isImplicitCell(r, m_columnIndices.at(c)) ? TXshCell() : cell;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Need to restore rows starting with implicit cells that were converted to
|
||||
// actual cells by this process
|
||||
m_beforeCells.reset(new TXshCell[m_columnIndices.size()]);
|
||||
int k = 0;
|
||||
TXsheetP xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
|
||||
for (int c = 0; c < m_columnIndices.size(); ++c) {
|
||||
const TXshCell &cell = xsh->getCell(m_r0, m_columnIndices.at(c));
|
||||
m_beforeCells[k++] =
|
||||
xsh->isImplicitCell(m_r0, m_columnIndices.at(c)) ? TXshCell() : cell;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -178,6 +191,15 @@ void AutoInputCellNumberUndo::undo() const {
|
|||
} else { // on insert case, remove inserted cells
|
||||
for (int c = 0; c < m_columnIndices.size(); ++c)
|
||||
xsh->removeCells(m_r0, m_columnIndices.at(c), m_rowsCount);
|
||||
|
||||
int k = 0;
|
||||
for (int c = 0; c < m_columnIndices.size(); ++c) {
|
||||
if (m_beforeCells[k].isEmpty())
|
||||
xsh->clearCells(m_r0, m_columnIndices.at(c));
|
||||
else
|
||||
xsh->setCell(m_r0, m_columnIndices.at(c), m_beforeCells[k]);
|
||||
k++;
|
||||
}
|
||||
}
|
||||
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "toonz/tcolumnfx.h"
|
||||
#include "toonz/fxdag.h"
|
||||
#include "toonz/txshlevelcolumn.h"
|
||||
#include "toonz/preferences.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
@ -194,7 +195,12 @@ void TCellData::cloneZeraryFx(int index, std::vector<TXshCell> &cells) const {
|
|||
newFxLevel->setColumn(newFxColumn);
|
||||
// replace the zerary fx cells by the new fx
|
||||
int r;
|
||||
for (r = firstNotEmptyIndex; r < (index + 1) * m_rowCount; r++)
|
||||
cells[r] = TXshCell(newFxLevel, m_cells[r].getFrameId());
|
||||
for (r = firstNotEmptyIndex; r < (index + 1) * m_rowCount; r++) {
|
||||
if (Preferences::instance()->isImplicitHoldEnabled() &&
|
||||
m_cells[r].getFrameId().isEmptyFrame())
|
||||
cells[r] = TXshCell(0, m_cells[r].getFrameId());
|
||||
else
|
||||
cells[r] = TXshCell(newFxLevel, m_cells[r].getFrameId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
#include "toonz/levelset.h"
|
||||
#include "toonz/tstageobjecttree.h"
|
||||
#include "toonz/stage.h"
|
||||
#include "toonz/txshzeraryfxlevel.h"
|
||||
#include "toonz/txshpalettelevel.h"
|
||||
#include "vectorizerpopup.h"
|
||||
#include "tools/rasterselection.h"
|
||||
#include "tools/strokeselection.h"
|
||||
|
@ -1264,6 +1266,47 @@ public:
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class StopFrameHoldUndo final : public TUndo {
|
||||
TXshLevel *m_level;
|
||||
TXshCell m_oldCell;
|
||||
int m_row;
|
||||
int m_col;
|
||||
|
||||
public:
|
||||
StopFrameHoldUndo(TXshLevel *level, int row, int col, TXshCell oldCell)
|
||||
: m_level(level), m_row(row), m_col(col), m_oldCell(oldCell) {}
|
||||
|
||||
~StopFrameHoldUndo() {}
|
||||
|
||||
void undo() const override {
|
||||
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
|
||||
|
||||
xsh->clearCells(m_row, m_col, 1);
|
||||
xsh->setCell(m_row, m_col, m_oldCell);
|
||||
|
||||
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
|
||||
}
|
||||
|
||||
void redo() const override {
|
||||
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
|
||||
|
||||
xsh->setCell(m_row, m_col, TXshCell(m_level, TFrameId::STOP_FRAME));
|
||||
|
||||
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
|
||||
}
|
||||
|
||||
int getSize() const override { return sizeof(*this); }
|
||||
|
||||
QString getHistoryString() override {
|
||||
return QObject::tr("Set Stop Frame Hold");
|
||||
}
|
||||
|
||||
int getHistoryType() override { return HistoryType::Xsheet; }
|
||||
//-----------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class DuplicateDrawingUndo final : public ToolUtils::TToolUndo {
|
||||
TFrameId origFrameId;
|
||||
TFrameId dupFrameId;
|
||||
|
@ -1511,6 +1554,7 @@ void TCellSelection::enableCommands() {
|
|||
&TCellSelection::createBlankDrawings);
|
||||
enableCommand(this, MI_Duplicate, &TCellSelection::duplicateFrames);
|
||||
enableCommand(this, MI_PasteDuplicate, &TCellSelection::pasteDuplicateCells);
|
||||
enableCommand(this, MI_StopFrameHold, &TCellSelection::stopFrameHold);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Used in RenameCellField::eventFilter()
|
||||
|
@ -1555,7 +1599,8 @@ bool TCellSelection::isEnabledCommand(
|
|||
MI_ConvertToToonzRaster,
|
||||
MI_ConvertVectorToVector,
|
||||
MI_CreateBlankDrawing,
|
||||
MI_FillEmptyCell};
|
||||
MI_FillEmptyCell,
|
||||
MI_StopFrameHold};
|
||||
return commands.contains(commandId);
|
||||
}
|
||||
|
||||
|
@ -2714,8 +2759,9 @@ void TCellSelection::createBlankDrawing(int row, int col, bool multiple) {
|
|||
|
||||
TXshCell cell = xsh->getCell(row, col);
|
||||
TXshSimpleLevel *sl = cell.getSimpleLevel();
|
||||
bool isStopFrame = cell.getFrameId().isStopFrame();
|
||||
|
||||
if (!img || !sl) {
|
||||
if ((!img || !sl) && !isStopFrame) {
|
||||
//----- Restore previous states of autocreation
|
||||
if (!isAutoCreateEnabled)
|
||||
Preferences::instance()->setValue(EnableAutocreation, false, false);
|
||||
|
@ -2738,8 +2784,12 @@ void TCellSelection::createBlankDrawing(int row, int col, bool multiple) {
|
|||
false);
|
||||
//------------------
|
||||
if (!multiple)
|
||||
DVGui::warning(QObject::tr(
|
||||
"Unable to replace the current drawing with a blank drawing"));
|
||||
if (isStopFrame)
|
||||
DVGui::warning(QObject::tr(
|
||||
"Unable to replace a Stop Frame Hold with a blank drawing"));
|
||||
else
|
||||
DVGui::warning(QObject::tr(
|
||||
"Unable to replace the current drawing with a blank drawing"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2787,6 +2837,98 @@ void TCellSelection::createBlankDrawings() {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void TCellSelection::stopFrameHold(int row, int col, bool multiple) {
|
||||
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
|
||||
|
||||
if (col < 0) {
|
||||
if (!multiple)
|
||||
DVGui::warning(QObject::tr(
|
||||
"Unable to create a stop frame hold on the camera column"));
|
||||
return;
|
||||
}
|
||||
|
||||
TXshColumn *column = xsh->getColumn(col);
|
||||
if (column && column->isLocked()) {
|
||||
if (!multiple) DVGui::warning(QObject::tr("The current column is locked"));
|
||||
return;
|
||||
}
|
||||
|
||||
TApp::instance()->getCurrentColumn()->setColumnIndex(col);
|
||||
TApp::instance()->getCurrentFrame()->setCurrentFrame(row + 1);
|
||||
|
||||
TXshLevel *level = TApp::instance()->getCurrentLevel()->getLevel();
|
||||
if (!level) {
|
||||
int r0, r1;
|
||||
xsh->getCellRange(col, r0, r1);
|
||||
for (int r = std::min(r1, row); r >= r0; r--) {
|
||||
TXshCell cell = xsh->getCell(r, col);
|
||||
if (cell.isEmpty()) continue;
|
||||
level = cell.m_level.getPointer();
|
||||
if (!level) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (level) {
|
||||
int levelType = level->getType();
|
||||
if (levelType == SND_XSHLEVEL || levelType == SND_TXT_XSHLEVEL) {
|
||||
if (!multiple)
|
||||
DVGui::warning(QObject::tr(
|
||||
"Cannot create a stop frame hold on the current column"));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!multiple)
|
||||
DVGui::warning(QObject::tr(
|
||||
"Cannot create a stop from hold on a column without a level"));
|
||||
return;
|
||||
}
|
||||
|
||||
TXshLevel *lvl = level->getSimpleLevel();
|
||||
if (!lvl) lvl = level->getChildLevel();
|
||||
if (!lvl) lvl = dynamic_cast<TXshLevel *>(level->getPaletteLevel());
|
||||
if (!lvl) lvl = dynamic_cast<TXshLevel *>(level->getZeraryFxLevel());
|
||||
|
||||
if (!lvl) {
|
||||
if (!multiple)
|
||||
DVGui::warning(QObject::tr(
|
||||
"Unable to create a stop frame hold on the current column"));
|
||||
return;
|
||||
}
|
||||
|
||||
TXshCell cell;
|
||||
if (!xsh->isImplicitCell(row, col)) cell = xsh->getCell(row, col);
|
||||
|
||||
StopFrameHoldUndo *undo = new StopFrameHoldUndo(lvl, row, col, cell);
|
||||
TUndoManager::manager()->add(undo);
|
||||
|
||||
undo->redo();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void TCellSelection::stopFrameHold() {
|
||||
int col = TApp::instance()->getCurrentColumn()->getColumnIndex();
|
||||
int row = TApp::instance()->getCurrentFrame()->getFrameIndex();
|
||||
|
||||
int r0, c0, r1, c1;
|
||||
getSelectedCells(r0, c0, r1, c1);
|
||||
|
||||
bool multiple = (r1 - r0 > 1) || (c1 - c0 > 1);
|
||||
|
||||
TUndoManager::manager()->beginBlock();
|
||||
for (int c = c0; c <= c1; c++) {
|
||||
for (int r = r0; r <= r1; r++) {
|
||||
stopFrameHold(r, c, multiple);
|
||||
}
|
||||
}
|
||||
TUndoManager::manager()->endBlock();
|
||||
|
||||
TApp::instance()->getCurrentColumn()->setColumnIndex(col);
|
||||
TApp::instance()->getCurrentFrame()->setCurrentFrame(row + 1);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void TCellSelection::duplicateFrame(int row, int col, bool multiple) {
|
||||
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
|
||||
|
||||
|
@ -2811,7 +2953,7 @@ void TCellSelection::duplicateFrame(int row, int col, bool multiple) {
|
|||
Preferences::instance()->isAnimationSheetEnabled()) {
|
||||
int r0, r1;
|
||||
xsh->getCellRange(col, r0, r1);
|
||||
for (int r = std::min(r1, row); r > r0; r--) {
|
||||
for (int r = std::min(r1, row); r >= r0; r--) {
|
||||
TXshCell cell = xsh->getCell(r, col);
|
||||
if (cell.isEmpty()) continue;
|
||||
level = cell.m_level.getPointer();
|
||||
|
@ -2838,7 +2980,6 @@ void TCellSelection::duplicateFrame(int row, int col, bool multiple) {
|
|||
|
||||
TXshCell targetCell = xsh->getCell(row, col);
|
||||
TXshCell prevCell = xsh->getCell(row - 1, col);
|
||||
;
|
||||
|
||||
// check if we use the current cell to duplicate or the previous cell
|
||||
if (!targetCell.isEmpty() && targetCell != prevCell) {
|
||||
|
@ -2849,6 +2990,12 @@ void TCellSelection::duplicateFrame(int row, int col, bool multiple) {
|
|||
row++;
|
||||
}
|
||||
|
||||
if (prevCell.getFrameId().isStopFrame()) {
|
||||
if (!xsh->isImplicitCell(row - 1, col) && !multiple)
|
||||
DVGui::warning(QObject::tr("Cannot duplicate a Stop Frame Hold"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (prevCell.isEmpty() || !(prevCell.m_level->getSimpleLevel())) return;
|
||||
|
||||
TXshSimpleLevel *sl = prevCell.getSimpleLevel();
|
||||
|
|
|
@ -125,6 +125,8 @@ public:
|
|||
|
||||
void createBlankDrawing(int row, int col, bool inRange);
|
||||
void createBlankDrawings();
|
||||
void stopFrameHold(int row, int col, bool inRange);
|
||||
void stopFrameHold();
|
||||
void fillEmptyCell();
|
||||
};
|
||||
|
||||
|
|
|
@ -209,7 +209,7 @@ void IncrementUndo::undo() const {
|
|||
const TRect &r = m_undoCells[i].first;
|
||||
int size = r.x1 - r.x0 + 1;
|
||||
|
||||
if (m_undoCells[i].second.isEmpty())
|
||||
if (m_undoCells[i].second.getFrameId().isNoFrame())
|
||||
xsh->removeCells(r.x0, r.y0, size);
|
||||
else {
|
||||
xsh->insertCells(r.x0, r.y0, size);
|
||||
|
@ -387,11 +387,13 @@ StepUndo::StepUndo(int r0, int c0, int r1, int c1, int step)
|
|||
assert(m_rowsCount > 0 && m_colsCount > 0 && step > 0);
|
||||
assert(m_cells);
|
||||
|
||||
int k = 0;
|
||||
TXsheetP xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
|
||||
int k = 0;
|
||||
for (int r = r0; r <= r1; ++r)
|
||||
for (int c = c0; c <= c1; ++c)
|
||||
m_cells[k++] =
|
||||
TApp::instance()->getCurrentXsheet()->getXsheet()->getCell(r, c);
|
||||
for (int c = c0; c <= c1; ++c) {
|
||||
const TXshCell &cell = xsh->getCell(r, c);
|
||||
m_cells[k++] = xsh->isImplicitCell(r, c) ? TXshCell() : cell;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -489,11 +491,13 @@ EachUndo::EachUndo(int r0, int c0, int r1, int c1, int each)
|
|||
assert(m_rowsCount > 0 && m_colsCount > 0 && each > 0);
|
||||
assert(m_cells);
|
||||
|
||||
int k = 0;
|
||||
int k = 0;
|
||||
TXsheetP xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
|
||||
for (int r = r0; r <= r1; ++r)
|
||||
for (int c = c0; c <= c1; ++c)
|
||||
m_cells[k++] =
|
||||
TApp::instance()->getCurrentXsheet()->getXsheet()->getCell(r, c);
|
||||
for (int c = c0; c <= c1; ++c) {
|
||||
const TXshCell &cell = xsh->getCell(r, c);
|
||||
m_cells[k++] = xsh->isImplicitCell(r, c) ? TXshCell() : cell;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -598,13 +602,16 @@ ReframeUndo::ReframeUndo(int r0, int r1, std::vector<int> columnIndeces,
|
|||
, m_withBlank(withBlank) {
|
||||
m_nr = m_r1 - m_r0 + 1;
|
||||
assert(m_nr > 0);
|
||||
m_cells.reset(new TXshCell[m_nr * (int)m_columnIndeces.size()]);
|
||||
m_cells.reset(new TXshCell[(m_nr + 1) * (int)m_columnIndeces.size()]);
|
||||
assert(m_cells);
|
||||
int k = 0;
|
||||
for (int r = r0; r <= r1; r++)
|
||||
for (int c = 0; c < (int)m_columnIndeces.size(); c++)
|
||||
m_cells[k++] = TApp::instance()->getCurrentXsheet()->getXsheet()->getCell(
|
||||
r, m_columnIndeces[c]);
|
||||
int k = 0;
|
||||
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
|
||||
for (int r = r0; r <= (r1 + 1); r++)
|
||||
for (int c = 0; c < (int)m_columnIndeces.size(); c++) {
|
||||
const TXshCell &cell = xsh->getCell(r, m_columnIndeces[c]);
|
||||
m_cells[k++] =
|
||||
xsh->isImplicitCell(r, m_columnIndeces[c]) ? TXshCell() : cell;
|
||||
}
|
||||
|
||||
m_newRows.clear();
|
||||
}
|
||||
|
@ -633,7 +640,7 @@ void ReframeUndo::undo() const {
|
|||
|
||||
if (m_cells) {
|
||||
int k = 0;
|
||||
for (int r = m_r0; r <= m_r1; r++)
|
||||
for (int r = m_r0; r <= m_r1 + 1; r++)
|
||||
for (int c = 0; c < m_columnIndeces.size(); c++) {
|
||||
if (m_cells[k].isEmpty())
|
||||
xsh->clearCells(r, m_columnIndeces[c]);
|
||||
|
@ -834,10 +841,10 @@ ResetStepUndo::ResetStepUndo(int r0, int c0, int r1, int c1)
|
|||
TXshCell prevCell;
|
||||
m_insertedCells[c] = 0;
|
||||
|
||||
TXsheetP xsh = app->getCurrentXsheet()->getXsheet();
|
||||
for (int r = r0; r <= r1; ++r) {
|
||||
const TXshCell &cell =
|
||||
app->getCurrentXsheet()->getXsheet()->getCell(r, c);
|
||||
m_cells[k++] = cell;
|
||||
const TXshCell &cell = xsh->getCell(r, c);
|
||||
m_cells[k++] = xsh->isImplicitCell(r, c) ? TXshCell() : cell;
|
||||
|
||||
if (prevCell != cell) {
|
||||
prevCell = cell;
|
||||
|
@ -934,10 +941,10 @@ IncreaseStepUndo::IncreaseStepUndo(int r0, int c0, int r1, int c1)
|
|||
TXshCell prevCell;
|
||||
m_insertedCells[c] = 0;
|
||||
|
||||
TXsheetP xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
|
||||
for (int r = r0; r <= r1; ++r) {
|
||||
const TXshCell &cell =
|
||||
TApp::instance()->getCurrentXsheet()->getXsheet()->getCell(r, c);
|
||||
m_cells[k++] = cell;
|
||||
const TXshCell &cell = xsh->getCell(r, c);
|
||||
m_cells[k++] = xsh->isImplicitCell(r, c) ? TXshCell() : cell;
|
||||
|
||||
if (prevCell != cell) {
|
||||
prevCell = cell;
|
||||
|
@ -1045,19 +1052,18 @@ DecreaseStepUndo::DecreaseStepUndo(int r0, int c0, int r1, int c1)
|
|||
, m_newR1(m_r1) {
|
||||
assert(m_cells);
|
||||
|
||||
int k = 0;
|
||||
int k = 0;
|
||||
TXsheetP xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
|
||||
for (int c = c0; c <= c1; ++c) {
|
||||
TXshCell prevCell =
|
||||
TApp::instance()->getCurrentXsheet()->getXsheet()->getCell(r0, c);
|
||||
TXshCell prevCell = xsh->getCell(r0, c);
|
||||
m_removedCells[c] = 0;
|
||||
|
||||
bool removed = false;
|
||||
m_cells[k++] = prevCell;
|
||||
m_cells[k++] = xsh->isImplicitCell(r0, c) ? TXshCell() : prevCell;
|
||||
|
||||
for (int r = r0 + 1; r <= r1; ++r) {
|
||||
const TXshCell &cell =
|
||||
TApp::instance()->getCurrentXsheet()->getXsheet()->getCell(r, c);
|
||||
m_cells[k++] = cell;
|
||||
const TXshCell &cell = xsh->getCell(r, c);
|
||||
m_cells[k++] = xsh->isImplicitCell(r, c) ? TXshCell() : cell;
|
||||
|
||||
if (prevCell == cell) {
|
||||
if (!removed) {
|
||||
|
@ -1120,7 +1126,8 @@ void TCellSelection::decreaseStepCells() {
|
|||
for (int i = 1; sameCells; i++) {
|
||||
nextCell = xsh->getCell(row + i, col);
|
||||
if (nextCell.m_frameId == cell.m_frameId &&
|
||||
nextCell.m_level == cell.m_level) {
|
||||
nextCell.m_level == cell.m_level &&
|
||||
!xsh->isImplicitCell(row + i, col)) {
|
||||
r1 = row + i;
|
||||
} else
|
||||
sameCells = false;
|
||||
|
@ -1595,20 +1602,35 @@ void CloneLevelUndo::insertCells() const {
|
|||
m_insertedColumns.insert(colIndex);
|
||||
}
|
||||
|
||||
bool useImplicitHold = Preferences::instance()->isImplicitHoldEnabled();
|
||||
|
||||
// Now, re-traverse the selected range, and add corresponding cells
|
||||
// in the destination range
|
||||
for (int c = m_range.m_c0; c <= m_range.m_c1; ++c) {
|
||||
TXshCell prevCell;
|
||||
TXshLevelP lastLevel = 0;
|
||||
for (int r = m_range.m_r0; r <= m_range.m_r1; ++r) {
|
||||
const TXshCell &srcCell = xsh->getCell(r, c);
|
||||
TXshCell srcCell = xsh->getCell(r, c);
|
||||
if (useImplicitHold) {
|
||||
if (r > m_range.m_r0 &&
|
||||
(prevCell == srcCell || xsh->isImplicitCell(r, c)))
|
||||
srcCell = TXshCell();
|
||||
prevCell = srcCell;
|
||||
}
|
||||
if (TXshSimpleLevel *srcSl = srcCell.getSimpleLevel()) {
|
||||
std::map<TXshSimpleLevel *, TXshLevelP>::iterator lt =
|
||||
m_insertedLevels.find(srcSl);
|
||||
if (lt != m_insertedLevels.end()) {
|
||||
lastLevel = lt->second;
|
||||
TXshCell dstCell(lt->second, srcCell.getFrameId());
|
||||
xsh->setCell(r, c + m_range.getColCount(), dstCell);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (useImplicitHold &&
|
||||
!xsh->getCell(m_range.m_r1, c + m_range.getColCount()).isEmpty())
|
||||
xsh->setCell(m_range.m_r1 + 1, c + m_range.getColCount(),
|
||||
TXshCell(lastLevel, TFrameId::STOP_FRAME));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
79
toonz/sources/toonz/icons/dark/actions/16/implicit_hold.svg
Normal file
79
toonz/sources/toonz/icons/dark/actions/16/implicit_hold.svg
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
version="1.1"
|
||||
xml:space="preserve"
|
||||
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"
|
||||
id="svg20"
|
||||
sodipodi:docname="implicit_hold.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
|
||||
id="metadata26"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs24" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1013"
|
||||
id="namedview22"
|
||||
showgrid="true"
|
||||
inkscape:zoom="51.250051"
|
||||
inkscape:cx="8.0000125"
|
||||
inkscape:cy="7.999996"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="new_vector_level"
|
||||
showguides="false"><inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid833" /></sodipodi:namedview>
|
||||
<g
|
||||
transform="matrix(1,0,0,1,-170,-210)"
|
||||
id="g18">
|
||||
<g
|
||||
id="new_vector_level"
|
||||
transform="matrix(1,0,0,1,60,-20)">
|
||||
|
||||
|
||||
|
||||
<g
|
||||
style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"
|
||||
transform="matrix(-0.110345,0,0,0.121212,142.22074,211.09094)"
|
||||
id="bg-1"><rect
|
||||
id="rect2-3"
|
||||
style="fill:#878787;fill-opacity:0"
|
||||
height="132"
|
||||
width="145"
|
||||
y="156"
|
||||
x="147" /></g><g
|
||||
transform="translate(109.99996,229.99997)"
|
||||
style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"
|
||||
id="g4549"><path
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 143.025,25 C 144.116,25 145,24.116 145,23.025 V 12.984 c 0,-0.527 -0.209,-1.031 -0.581,-1.403 C 144.047,11.209 143.543,11 143.016,11 c -2.663,0 -7.369,0 -10.032,0 -0.527,0 -1.031,0.209 -1.403,0.581 -0.372,0.372 -0.581,0.876 -0.581,1.403 v 10.032 c 0,0.527 0.209,1.031 0.581,1.403 0.372,0.372 0.876,0.581 1.403,0.581 2.666,0 7.378,0 10.041,0 z m 0.014,-1 C 143.57,24 144,23.57 144,23.039 V 13.017 c 0,-0.269 -0.107,-0.528 -0.298,-0.719 C 143.511,12.107 143.252,12 142.983,12 h -9.966 c -0.269,0 -0.528,0.107 -0.719,0.298 -0.191,0.191 -0.298,0.45 -0.298,0.719 v 9.966 c 0,0.269 0.107,0.528 0.298,0.719 0.191,0.191 0.45,0.298 0.719,0.298 z M 136,13.5 c 0,-0.133 -0.053,-0.26 -0.146,-0.354 C 135.76,13.053 135.633,13 135.5,13 c -0.555,0 -1.445,0 -2,0 -0.133,0 -0.26,0.053 -0.354,0.146 C 133.053,13.24 133,13.367 133,13.5 c 0,0.133 0.053,0.26 0.146,0.354 0.094,0.093 0.221,0.146 0.354,0.146 0.555,0 1.445,0 2,0 0.133,0 0.26,-0.053 0.354,-0.146 C 135.947,13.76 136,13.633 136,13.5 Z m 3,0 c 0,-0.133 -0.053,-0.26 -0.146,-0.354 C 138.76,13.053 138.633,13 138.5,13 c -0.305,0 -0.695,0 -1,0 -0.133,0 -0.26,0.053 -0.354,0.146 C 137.053,13.24 137,13.367 137,13.5 c 0,0.133 0.053,0.26 0.146,0.354 0.094,0.093 0.221,0.146 0.354,0.146 0.305,0 0.695,0 1,0 0.133,0 0.26,-0.053 0.354,-0.146 C 138.947,13.76 139,13.633 139,13.5 Z m 4,0 c 0,-0.133 -0.053,-0.26 -0.146,-0.354 C 142.76,13.053 142.633,13 142.5,13 c -0.555,0 -1.445,0 -2,0 -0.133,0 -0.26,0.053 -0.354,0.146 C 140.053,13.24 140,13.367 140,13.5 c 0,0.133 0.053,0.26 0.146,0.354 0.094,0.093 0.221,0.146 0.354,0.146 0.555,0 1.445,0 2,0 0.133,0 0.26,-0.053 0.354,-0.146 C 142.947,13.76 143,13.633 143,13.5 Z"
|
||||
id="path5-1"
|
||||
style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"
|
||||
transform="translate(-129.99996,-9.999966)" /><g
|
||||
transform="matrix(0.71689545,0,0,0.56820456,-90.925068,-1.2051139)"
|
||||
id="g7-2-9"
|
||||
style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"><path
|
||||
sodipodi:nodetypes="ssssssssssssssssssssssssccccccccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 143.025,25 C 144.116,25 145,24.116 145,23.025 V 12.984 c 0,-0.527 -0.209,-1.031 -0.581,-1.403 C 144.047,11.209 143.543,11 143.016,11 h -10.032 c -0.527,0 -1.031,0.209 -1.403,0.581 -0.372,0.372 -0.581,0.876 -0.581,1.403 v 10.032 c 0,0.527 0.209,1.031 0.581,1.403 0.372,0.372 0.876,0.581 1.403,0.581 z m 0.014,-1 C 143.57,24 144,23.57 144,23.039 V 13.017 c 0,-0.269 -0.107,-0.528 -0.298,-0.719 C 143.511,12.107 143.252,12 142.983,12 h -9.966 c -0.269,0 -0.528,0.107 -0.719,0.298 -0.191,0.191 -0.298,0.45 -0.298,0.719 v 9.966 c 0,0.269 0.107,0.528 0.298,0.719 0.191,0.191 0.45,0.298 0.719,0.298 z m -6.83211,-11.319507 -3.41581,10e-7 v 1.75993 l 3.41965,-2e-6 z m 2.78822,0 h -2.01706 l -0.0135,1.759929 h 2.02473 z m 4.19839,10e-7 -3.4197,-10e-7 -0.006,1.759929 3.41008,2e-6 z"
|
||||
id="path5-1-8" /></g></g></g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.1 KiB |
|
@ -0,0 +1,75 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
version="1.1"
|
||||
xml:space="preserve"
|
||||
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"
|
||||
id="svg20"
|
||||
sodipodi:docname="implicit_hold_on.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
|
||||
id="metadata26"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs24"><pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern" /></defs><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1013"
|
||||
id="namedview22"
|
||||
showgrid="true"
|
||||
inkscape:zoom="51.25"
|
||||
inkscape:cx="8"
|
||||
inkscape:cy="8"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg20"><inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid833" /></sodipodi:namedview>
|
||||
|
||||
<g
|
||||
style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"
|
||||
transform="matrix(-0.110345,0,0,0.121212,32.22074,-18.909056)"
|
||||
id="bg-1"><rect
|
||||
id="rect2-3"
|
||||
style="fill:#878787;fill-opacity:0"
|
||||
height="132"
|
||||
width="145"
|
||||
y="156"
|
||||
x="147" /></g><g
|
||||
style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"
|
||||
id="g7-2"
|
||||
transform="translate(-129.99996,-9.999966)" /><g
|
||||
id="g4549"><path
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 143.025,25 C 144.116,25 145,24.116 145,23.025 V 12.984 c 0,-0.527 -0.209,-1.031 -0.581,-1.403 C 144.047,11.209 143.543,11 143.016,11 c -2.663,0 -7.369,0 -10.032,0 -0.527,0 -1.031,0.209 -1.403,0.581 -0.372,0.372 -0.581,0.876 -0.581,1.403 v 10.032 c 0,0.527 0.209,1.031 0.581,1.403 0.372,0.372 0.876,0.581 1.403,0.581 2.666,0 7.378,0 10.041,0 z m 0.014,-1 C 143.57,24 144,23.57 144,23.039 V 13.017 c 0,-0.269 -0.107,-0.528 -0.298,-0.719 C 143.511,12.107 143.252,12 142.983,12 h -9.966 c -0.269,0 -0.528,0.107 -0.719,0.298 -0.191,0.191 -0.298,0.45 -0.298,0.719 v 9.966 c 0,0.269 0.107,0.528 0.298,0.719 0.191,0.191 0.45,0.298 0.719,0.298 z M 136,13.5 c 0,-0.133 -0.053,-0.26 -0.146,-0.354 C 135.76,13.053 135.633,13 135.5,13 c -0.555,0 -1.445,0 -2,0 -0.133,0 -0.26,0.053 -0.354,0.146 C 133.053,13.24 133,13.367 133,13.5 c 0,0.133 0.053,0.26 0.146,0.354 0.094,0.093 0.221,0.146 0.354,0.146 0.555,0 1.445,0 2,0 0.133,0 0.26,-0.053 0.354,-0.146 C 135.947,13.76 136,13.633 136,13.5 Z m 3,0 c 0,-0.133 -0.053,-0.26 -0.146,-0.354 C 138.76,13.053 138.633,13 138.5,13 c -0.305,0 -0.695,0 -1,0 -0.133,0 -0.26,0.053 -0.354,0.146 C 137.053,13.24 137,13.367 137,13.5 c 0,0.133 0.053,0.26 0.146,0.354 0.094,0.093 0.221,0.146 0.354,0.146 0.305,0 0.695,0 1,0 0.133,0 0.26,-0.053 0.354,-0.146 C 138.947,13.76 139,13.633 139,13.5 Z m 4,0 c 0,-0.133 -0.053,-0.26 -0.146,-0.354 C 142.76,13.053 142.633,13 142.5,13 c -0.555,0 -1.445,0 -2,0 -0.133,0 -0.26,0.053 -0.354,0.146 C 140.053,13.24 140,13.367 140,13.5 c 0,0.133 0.053,0.26 0.146,0.354 0.094,0.093 0.221,0.146 0.354,0.146 0.555,0 1.445,0 2,0 0.133,0 0.26,-0.053 0.354,-0.146 C 142.947,13.76 143,13.633 143,13.5 Z"
|
||||
id="path5-1"
|
||||
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"
|
||||
transform="translate(-129.99996,-9.999966)" /><g
|
||||
transform="matrix(0.71689545,0,0,0.56820456,-90.925068,-1.2051139)"
|
||||
id="g7-2-9"
|
||||
style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"><path
|
||||
sodipodi:nodetypes="ssssssssssssssssssssssssccccccccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 143.025,25 C 144.116,25 145,24.116 145,23.025 V 12.984 c 0,-0.527 -0.209,-1.031 -0.581,-1.403 C 144.047,11.209 143.543,11 143.016,11 h -10.032 c -0.527,0 -1.031,0.209 -1.403,0.581 -0.372,0.372 -0.581,0.876 -0.581,1.403 v 10.032 c 0,0.527 0.209,1.031 0.581,1.403 0.372,0.372 0.876,0.581 1.403,0.581 z m 0.014,-1 C 143.57,24 144,23.57 144,23.039 V 13.017 c 0,-0.269 -0.107,-0.528 -0.298,-0.719 C 143.511,12.107 143.252,12 142.983,12 h -9.966 c -0.269,0 -0.528,0.107 -0.719,0.298 -0.191,0.191 -0.298,0.45 -0.298,0.719 v 9.966 c 0,0.269 0.107,0.528 0.298,0.719 0.191,0.191 0.45,0.298 0.719,0.298 z m -6.83211,-11.319507 -3.41581,10e-7 v 1.75993 l 3.41965,-2e-6 z m 2.78822,0 h -2.01706 l -0.0135,1.759929 2.02473,0 z m 4.19839,10e-7 -3.4197,-10e-7 -0.006,1.759929 3.41008,2e-6 z"
|
||||
id="path5-1-8" /></g></g></svg>
|
After Width: | Height: | Size: 5 KiB |
|
@ -0,0 +1,80 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
version="1.1"
|
||||
xml:space="preserve"
|
||||
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"
|
||||
id="svg12"
|
||||
sodipodi:docname="stop_frame_hold.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
|
||||
id="metadata18"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs16">
|
||||
|
||||
</defs><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1672"
|
||||
inkscape:window-height="865"
|
||||
id="namedview14"
|
||||
showgrid="true"
|
||||
inkscape:zoom="41.7193"
|
||||
inkscape:cx="11.121506"
|
||||
inkscape:cy="7.0977181"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg12"
|
||||
inkscape:snap-grids="true"><inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid827" /></sodipodi:namedview>
|
||||
<g
|
||||
transform="matrix(-1,0,0,1,126,-10)"
|
||||
id="add_cell">
|
||||
<g
|
||||
transform="matrix(0.110345,0,0,0.121212,93.7793,-8.90909)"
|
||||
id="bg">
|
||||
<rect
|
||||
id="rect2"
|
||||
style="fill:#878787;fill-opacity:0"
|
||||
height="132"
|
||||
width="145"
|
||||
y="156"
|
||||
x="147" />
|
||||
</g>
|
||||
<g
|
||||
id="g7"
|
||||
transform="matrix(-1,0,0,1,256,0)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5"
|
||||
d="m 145,21 v -8.016 c 0,-0.527 -0.209,-1.031 -0.581,-1.403 C 144.047,11.209 143.543,11 143.016,11 h -10.032 c -0.527,0 -1.031,0.209 -1.403,0.581 -0.372,0.372 -0.581,0.876 -0.581,1.403 v 10.032 c 0,0.527 0.209,1.031 0.581,1.403 0.372,0.372 0.876,0.581 1.403,0.581 H 141 c 0.265,0 0.52,-0.105 0.707,-0.293 l 3,-3 C 144.895,21.52 145,21.265 145,21 Z m -1,-1 v -6.983 c 0,-0.27 -0.107,-0.528 -0.298,-0.719 C 143.511,12.107 143.252,12 142.983,12 h -9.966 c -0.269,0 -0.528,0.107 -0.719,0.298 -0.191,0.191 -0.298,0.45 -0.298,0.719 v 9.966 c 0,0.269 0.107,0.528 0.298,0.719 0.191,0.191 0.449,0.298 0.719,0.298 H 140 v -4 z m -3,1 v 3 l 3,-3 z m -5,-7.5 c 0,-0.133 -0.053,-0.26 -0.146,-0.354 C 135.76,13.053 135.633,13 135.5,13 h -2 c -0.133,0 -0.26,0.053 -0.354,0.146 C 133.053,13.24 133,13.367 133,13.5 c 0,0.133 0.053,0.26 0.146,0.354 0.094,0.093 0.221,0.146 0.354,0.146 h 2 c 0.133,0 0.26,-0.053 0.354,-0.146 C 135.947,13.76 136,13.633 136,13.5 Z m 3,0 c 0,-0.133 -0.053,-0.26 -0.146,-0.354 C 138.76,13.053 138.633,13 138.5,13 h -1 c -0.133,0 -0.26,0.053 -0.354,0.146 C 137.053,13.24 137,13.367 137,13.5 c 0,0.133 0.053,0.26 0.146,0.354 0.094,0.093 0.221,0.146 0.354,0.146 h 1 c 0.133,0 0.26,-0.053 0.354,-0.146 C 138.947,13.76 139,13.633 139,13.5 Z m 4,0 c 0,-0.133 -0.053,-0.26 -0.146,-0.354 C 142.76,13.053 142.633,13 142.5,13 h -2 c -0.133,0 -0.26,0.053 -0.354,0.146 C 140.053,13.24 140,13.367 140,13.5 c 0,0.133 0.053,0.26 0.146,0.354 0.094,0.093 0.221,0.146 0.354,0.146 h 2 c 0.133,0 0.26,-0.053 0.354,-0.146 C 142.947,13.76 143,13.633 143,13.5 Z"
|
||||
sodipodi:nodetypes="sssssssssssccscssssssssscccccccscsscscsscsscsscscsscsscsscscsscs" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 4,6 6.256939,4.520606"
|
||||
id="path4542"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" /><path
|
||||
style="clip-rule:evenodd;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:2;stroke-opacity:1"
|
||||
d="M 12,6 4,12"
|
||||
id="path4542-0"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" /></svg>
|
After Width: | Height: | Size: 4.1 KiB |
|
@ -322,7 +322,9 @@ bool beforeCellsInsert(TXsheet *xsh, int row, int &col, int rowCount,
|
|||
int i = 0;
|
||||
TXshColumn *column = xsh->getColumn(col);
|
||||
|
||||
for (i = 0; i < rowCount && xsh->getCell(row + i, col).isEmpty(); i++) {
|
||||
for (i = 0; i < rowCount && (xsh->getCell(row + i, col).isEmpty() ||
|
||||
xsh->isImplicitCell(row + i, col));
|
||||
i++) {
|
||||
}
|
||||
int type = (column && !column->isEmpty()) ? column->getColumnType()
|
||||
: newLevelColumnType;
|
||||
|
@ -508,8 +510,10 @@ public:
|
|||
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
|
||||
for (c = m_col0; c <= m_col1; c++)
|
||||
for (r = m_row0; r <= m_row1; r++) {
|
||||
TXshSimpleLevel *oldLevel = xsh->getCell(r, c).getSimpleLevel();
|
||||
TFrameId fid = xsh->getCell(r, c).getFrameId();
|
||||
TXshCell cell;
|
||||
if (!xsh->isImplicitCell(r, c)) cell = xsh->getCell(r, c);
|
||||
TXshSimpleLevel *oldLevel = cell.getSimpleLevel();
|
||||
TFrameId fid = cell.getFrameId();
|
||||
QPair<int, int> cellId(r, c);
|
||||
m_oldLevels[cellId] = QPair<TXshSimpleLevelP, TFrameId>(oldLevel, fid);
|
||||
}
|
||||
|
|
|
@ -2061,6 +2061,8 @@ void MainWindow::defineActions() {
|
|||
createMenuCellsAction(MI_CreateBlankDrawing,
|
||||
QT_TR_NOOP("&Create Blank Drawing"), "Alt+D",
|
||||
"add_cell");
|
||||
createMenuCellsAction(MI_StopFrameHold, QT_TR_NOOP("&Stop Frame Hold"), "",
|
||||
"stop_frame_hold");
|
||||
createMenuCellsAction(MI_Duplicate, QT_TR_NOOP("&Duplicate Drawing "), "D",
|
||||
"duplicate_drawing");
|
||||
createMenuCellsAction(MI_Autorenumber, QT_TR_NOOP("&Autorenumber"), "",
|
||||
|
@ -2501,6 +2503,10 @@ void MainWindow::defineActions() {
|
|||
createToggle(MI_ViewerIndicator, QT_TR_NOOP("Toggle Viewer Indicators"), "",
|
||||
Preferences::instance()->isViewerIndicatorEnabled(),
|
||||
RightClickMenuCommandType);
|
||||
createToggle(MI_ToggleImplicitHold, QT_TR_NOOP("Toggle Implicit Hold"), "",
|
||||
Preferences::instance()->isImplicitHoldEnabled(),
|
||||
MiscCommandType, "implicit_hold",
|
||||
tr("Toggles the implicit hold of a frame to the next frame"));
|
||||
|
||||
// Tools
|
||||
|
||||
|
|
|
@ -537,6 +537,7 @@ void TopBar::loadMenubar() {
|
|||
addMenuItem(cellsMenu, MI_Autorenumber);
|
||||
addMenuItem(cellsMenu, MI_CreateBlankDrawing);
|
||||
addMenuItem(cellsMenu, MI_Duplicate);
|
||||
addMenuItem(cellsMenu, MI_StopFrameHold);
|
||||
addMenuItem(cellsMenu, MI_MergeFrames);
|
||||
addMenuItem(cellsMenu, MI_CloneLevel);
|
||||
cellsMenu->addSeparator();
|
||||
|
|
|
@ -153,6 +153,7 @@
|
|||
#define MI_Autorenumber "MI_Autorenumber"
|
||||
#define MI_CreateBlankDrawing "MI_CreateBlankDrawing"
|
||||
#define MI_FillEmptyCell "MI_FillEmptyCell"
|
||||
#define MI_StopFrameHold "MI_StopFrameHold"
|
||||
|
||||
#define MI_MergeFrames "MI_MergeFrames"
|
||||
#define MI_Reverse "MI_Reverse"
|
||||
|
@ -478,4 +479,6 @@
|
|||
#define MI_ToggleCreationInHoldCells "MI_ToggleCreationInHoldCells"
|
||||
#define MI_ToggleAutoStretch "MI_ToggleAutoStretch"
|
||||
|
||||
#define MI_ToggleImplicitHold "MI_ToggleImplicitHold"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1062,6 +1062,7 @@ QString PreferencesPopup::getUIString(PreferencesItemId id) {
|
|||
{EnableAutoStretch, tr("Enable Auto-stretch Frame")},
|
||||
{EnableCreationInHoldCells, tr("Enable Creation in Hold Cells")},
|
||||
{EnableAutoRenumber, tr("Enable Autorenumber")},
|
||||
{EnableImplicitHold, tr("Enable Implicit Hold")},
|
||||
{vectorSnappingTarget, tr("Vector Snapping:")},
|
||||
{saveUnpaintedInCleanup,
|
||||
tr("Keep Original Cleaned Up Drawings As Backup")},
|
||||
|
@ -1679,6 +1680,7 @@ QWidget* PreferencesPopup::createDrawingPage() {
|
|||
{
|
||||
insertUI(NumberingSystem, creationLay, getComboItemList(NumberingSystem));
|
||||
insertUI(EnableAutoStretch, creationLay);
|
||||
insertUI(EnableImplicitHold, creationLay);
|
||||
insertUI(EnableAutoRenumber, creationLay);
|
||||
}
|
||||
QGridLayout* autoCreationLay = insertGroupBoxUI(EnableAutocreation, lay);
|
||||
|
|
|
@ -64,11 +64,13 @@ public:
|
|||
assert(nr > 0 && nc > 0);
|
||||
m_cells.reset(new TXshCell[nr * nc]);
|
||||
assert(m_cells);
|
||||
int k = 0;
|
||||
int k = 0;
|
||||
TXsheetP xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
|
||||
for (int c = c0; c <= c1; c++)
|
||||
for (int r = r0; r <= r1; r++)
|
||||
m_cells[k++] =
|
||||
TApp::instance()->getCurrentXsheet()->getXsheet()->getCell(r, c);
|
||||
for (int r = r0; r <= r1; r++) {
|
||||
const TXshCell &cell = xsh->getCell(r, c);
|
||||
m_cells[k++] = xsh->isImplicitCell(r, c) ? TXshCell() : cell;
|
||||
}
|
||||
}
|
||||
|
||||
~TimeStretchUndo() {}
|
||||
|
@ -102,7 +104,7 @@ public:
|
|||
for (i = 0; i < nr; i++)
|
||||
xsh->setCell(i + m_r0, c, m_cells[i + nr * (c - m_c0)]);
|
||||
int dn = oldNr - nr;
|
||||
xsh->removeCells(m_r1, c, dn);
|
||||
xsh->removeCells(m_r1 + 1, c, dn);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -329,8 +329,10 @@
|
|||
<file>icons/dark/actions/16/auto_stretch_on.svg</file>
|
||||
<file>icons/dark/actions/16/create_in_hold.svg</file>
|
||||
<file>icons/dark/actions/16/create_in_hold_on.svg</file>
|
||||
<file>icons/dark/actions/16/implicit_hold.svg</file>
|
||||
<file>icons/dark/actions/16/implicit_hold_on.svg</file>
|
||||
|
||||
<file>icons/dark/actions/16/on_1s.svg</file>
|
||||
<file>icons/dark/actions/16/on_1s.svg</file>
|
||||
<file>icons/dark/actions/16/on_2s.svg</file>
|
||||
<file>icons/dark/actions/16/on_3s.svg</file>
|
||||
<file>icons/dark/actions/16/on_4s.svg</file>
|
||||
|
@ -361,6 +363,7 @@
|
|||
<file>icons/dark/actions/16/remove_cells.svg</file>
|
||||
<file>icons/dark/actions/16/duplicate_drawing.svg</file>
|
||||
<file>icons/dark/actions/16/tracking_options.svg</file>
|
||||
<file>icons/dark/actions/16/stop_frame_hold.svg</file>
|
||||
|
||||
<file>icons/dark/actions/16/camera_settings.svg</file>
|
||||
<file>icons/dark/actions/16/autoexpose.svg</file>
|
||||
|
|
|
@ -201,7 +201,9 @@ 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(r + j, c + i).isEmpty()) return false;
|
||||
if (!xsh->getCell(r + j, c + i).isEmpty() &&
|
||||
!xsh->isImplicitCell(r + j, c + i))
|
||||
return false;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1880,6 +1880,25 @@ void CellArea::drawFrameMarker(QPainter &p, const QPoint &xy, QColor color,
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CellArea::drawEndOfLevelMarker(QPainter &p, QRect rect, bool isStopFrame) {
|
||||
const Orientation *o = m_viewer->orientation();
|
||||
|
||||
QColor levelEndColor = m_viewer->getTextColor();
|
||||
QPoint topLeft = rect.topLeft();
|
||||
QPoint topRight = rect.topRight();
|
||||
if (!o->isVerticalTimeline() && isStopFrame) {
|
||||
QRect dragRect = o->rect(PredefinedRect::DRAG_AREA);
|
||||
topLeft.setY(topLeft.y() + dragRect.height());
|
||||
topRight.setY(topRight.y() + dragRect.height());
|
||||
}
|
||||
levelEndColor.setAlphaF(0.3);
|
||||
p.setPen(levelEndColor);
|
||||
p.drawLine(topLeft, rect.bottomRight());
|
||||
p.drawLine(topRight, rect.bottomLeft());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference,
|
||||
bool showLevelName) {
|
||||
const Orientation *o = m_viewer->orientation();
|
||||
|
@ -1907,8 +1926,14 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference,
|
|||
columnSelection->isColumnSelected(col);
|
||||
bool isSimpleView = m_viewer->getFrameZoomFactor() <=
|
||||
o->dimension(PredefinedDimension::SCALE_THRESHOLD);
|
||||
bool isImplicitCell = xsh->isImplicitCell(row, col);
|
||||
bool isStopFrame = isImplicitCell ? false : cell.getFrameId().isStopFrame();
|
||||
|
||||
if (row > 0) prevCell = xsh->getCell(row - 1, col); // cell in previous frame
|
||||
bool prevIsImplicit = false;
|
||||
if (row > 0) {
|
||||
prevCell = xsh->getCell(row - 1, col); // cell in previous frame
|
||||
prevIsImplicit = xsh->isImplicitCell(row - 1, col);
|
||||
}
|
||||
|
||||
bool sameLevel = prevCell.m_level.getPointer() == cell.m_level.getPointer();
|
||||
|
||||
|
@ -1931,7 +1956,12 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference,
|
|||
.translated(QPoint(x, y));
|
||||
cellRect.adjust(0, 0, -frameAdj.x(), -frameAdj.y());
|
||||
QRect rect = cellRect.adjusted(
|
||||
1, 1, (!o->isVerticalTimeline() && !nextCell.isEmpty() ? 2 : 0), 0);
|
||||
1, 1, (!o->isVerticalTimeline() && !nextCell.isEmpty() &&
|
||||
!xsh->isImplicitCell(row + 1, col) &&
|
||||
!nextCell.getFrameId().isStopFrame()
|
||||
? 2
|
||||
: 0),
|
||||
0);
|
||||
|
||||
QRect markRect =
|
||||
o->rect(PredefinedRect::CELL_MARK_AREA)
|
||||
|
@ -1988,7 +2018,8 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference,
|
|||
}
|
||||
|
||||
bool heldFrame = (!o->isVerticalTimeline() && sameLevel &&
|
||||
prevCell.m_frameId == cell.m_frameId);
|
||||
prevCell.m_frameId == cell.m_frameId) &&
|
||||
!isImplicitCell;
|
||||
drawFrameSeparator(p, row, col, false, heldFrame);
|
||||
|
||||
if (cell.isEmpty()) { // it means previous is not empty
|
||||
|
@ -2001,11 +2032,9 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference,
|
|||
p.drawEllipse(markRect);
|
||||
}
|
||||
|
||||
QColor levelEndColor = m_viewer->getTextColor();
|
||||
levelEndColor.setAlphaF(0.3);
|
||||
p.setPen(levelEndColor);
|
||||
p.drawLine(rect.topLeft(), rect.bottomRight());
|
||||
p.drawLine(rect.topRight(), rect.bottomLeft());
|
||||
// Implicit holds use Stop Frame Hold to denote end of level
|
||||
if (!Preferences::instance()->isImplicitHoldEnabled())
|
||||
drawEndOfLevelMarker(p, rect);
|
||||
|
||||
if (TApp::instance()->getCurrentFrame()->isEditingScene() &&
|
||||
!m_viewer->orientation()->isVerticalTimeline() &&
|
||||
|
@ -2024,6 +2053,8 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference,
|
|||
int levelType;
|
||||
m_viewer->getCellTypeAndColors(levelType, cellColor, sideColor, cell,
|
||||
isSelected);
|
||||
if (isImplicitCell) cellColor.setAlpha(m_viewer->getImplicitCellAlpha());
|
||||
if (isStopFrame) cellColor.setAlpha(0);
|
||||
}
|
||||
|
||||
// check if the level is scanned but not cleanupped
|
||||
|
@ -2044,17 +2075,8 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference,
|
|||
else
|
||||
p.fillRect(rect, QBrush(cellColor));
|
||||
|
||||
if (yetToCleanupCell) // ORIENTATION: what's this?
|
||||
{
|
||||
if (o->isVerticalTimeline())
|
||||
p.fillRect(rect.adjusted(rect.width() / 2, 0, 0, 0),
|
||||
(isSelected) ? m_viewer->getSelectedFullcolorColumnColor()
|
||||
: m_viewer->getFullcolorColumnColor());
|
||||
else
|
||||
p.fillRect(rect.adjusted(0, rect.height() / 2, 0, 0),
|
||||
(isSelected) ? m_viewer->getSelectedFullcolorColumnColor()
|
||||
: m_viewer->getFullcolorColumnColor());
|
||||
}
|
||||
// Implicit holds use Stop Frame Hold to denote end of level
|
||||
if (isStopFrame) drawEndOfLevelMarker(p, rect, true);
|
||||
|
||||
if (TApp::instance()->getCurrentFrame()->isEditingScene() &&
|
||||
!m_viewer->orientation()->isVerticalTimeline() &&
|
||||
|
@ -2062,13 +2084,27 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference,
|
|||
Preferences::instance()->isCurrentTimelineIndicatorEnabled())
|
||||
drawCurrentTimeIndicator(p, xy);
|
||||
|
||||
drawDragHandle(p, xy, sideColor);
|
||||
if (!isImplicitCell) {
|
||||
if (yetToCleanupCell) // ORIENTATION: what's this?
|
||||
{
|
||||
if (o->isVerticalTimeline())
|
||||
p.fillRect(rect.adjusted(rect.width() / 2, 0, 0, 0),
|
||||
(isSelected) ? m_viewer->getSelectedFullcolorColumnColor()
|
||||
: m_viewer->getFullcolorColumnColor());
|
||||
else
|
||||
p.fillRect(rect.adjusted(0, rect.height() / 2, 0, 0),
|
||||
(isSelected) ? m_viewer->getSelectedFullcolorColumnColor()
|
||||
: m_viewer->getFullcolorColumnColor());
|
||||
}
|
||||
|
||||
bool isLastRow = nextCell.isEmpty() ||
|
||||
cell.m_level.getPointer() != nextCell.m_level.getPointer();
|
||||
drawEndOfDragHandle(p, isLastRow, xy, cellColor);
|
||||
drawDragHandle(p, xy, sideColor);
|
||||
|
||||
drawLockedDottedLine(p, xsh->getColumn(col)->isLocked(), xy, cellColor);
|
||||
bool isLastRow = nextCell.isEmpty() ||
|
||||
cell.m_level.getPointer() != nextCell.m_level.getPointer();
|
||||
drawEndOfDragHandle(p, isLastRow, xy, cellColor);
|
||||
|
||||
drawLockedDottedLine(p, xsh->getColumn(col)->isLocked(), xy, cellColor);
|
||||
}
|
||||
|
||||
int distance, offset;
|
||||
TApp::instance()->getCurrentScene()->getScene()->getProperties()->getMarkers(
|
||||
|
@ -2096,11 +2132,13 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference,
|
|||
nameRect.adjust(0, 0, -frameAdj.x(), -frameAdj.y());
|
||||
|
||||
// draw text in red if the file does not exist
|
||||
bool isRed = false;
|
||||
TXshSimpleLevel *sl = cell.getSimpleLevel();
|
||||
if (sl && !sl->isFid(cell.m_frameId)) isRed = true;
|
||||
TXshChildLevel *cl = cell.getChildLevel();
|
||||
if (cl && cell.getFrameId().getNumber() - 1 >= cl->getFrameCount())
|
||||
bool isRed = false;
|
||||
TXshSimpleLevel *sl = cell.getSimpleLevel();
|
||||
if (sl && !cell.getFrameId().isStopFrame() && !sl->isFid(cell.m_frameId))
|
||||
isRed = true;
|
||||
TXshChildLevel *cl = cell.getChildLevel();
|
||||
if (cl && !cell.getFrameId().isStopFrame() &&
|
||||
cell.getFrameId().getNumber() - 1 >= cl->getFrameCount())
|
||||
isRed = true;
|
||||
QColor penColor =
|
||||
isRed ? QColor(m_viewer->getErrorTextColor()) : m_viewer->getTextColor();
|
||||
|
@ -2124,7 +2162,8 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference,
|
|||
// if the same level & same fId with the previous cell,
|
||||
// draw continue line
|
||||
QString fnum;
|
||||
if (sameLevel && prevCell.m_frameId == cell.m_frameId) {
|
||||
if ((sameLevel && prevCell.m_frameId == cell.m_frameId && !prevIsImplicit) ||
|
||||
isImplicitCell) {
|
||||
if (o->isVerticalTimeline()) {
|
||||
// not on line marker
|
||||
PredefinedLine which =
|
||||
|
@ -2161,7 +2200,8 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference,
|
|||
if (pegbar->isKeyframe(row)) return;
|
||||
}
|
||||
|
||||
drawFrameMarker(p, QPoint(x, y), (isRed ? Qt::red : Qt::black));
|
||||
if (!isStopFrame)
|
||||
drawFrameMarker(p, QPoint(x, y), (isRed ? Qt::red : Qt::black));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2169,7 +2209,9 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference,
|
|||
|
||||
// convert the last one digit of the frame number to alphabet
|
||||
// Ex. 12 -> 1B 21 -> 2A 30 -> 3
|
||||
if (Preferences::instance()->isShowFrameNumberWithLettersEnabled())
|
||||
if (fid.isStopFrame())
|
||||
fnum = "";
|
||||
else if (Preferences::instance()->isShowFrameNumberWithLettersEnabled())
|
||||
fnum = m_viewer->getFrameNumberWithLetters(fid.getNumber());
|
||||
else {
|
||||
QString frameNumber("");
|
||||
|
@ -2180,8 +2222,9 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference,
|
|||
fnum = frameNumber;
|
||||
}
|
||||
|
||||
int alignFlag =
|
||||
((showLevelName) ? Qt::AlignRight | Qt::AlignBottom : Qt::AlignCenter);
|
||||
int alignFlag = ((showLevelName && !fid.isStopFrame())
|
||||
? Qt::AlignRight | Qt::AlignBottom
|
||||
: Qt::AlignCenter);
|
||||
p.drawText(nameRect, alignFlag, fnum);
|
||||
}
|
||||
|
||||
|
@ -2193,9 +2236,11 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference,
|
|||
p.setPen(penColor);
|
||||
}
|
||||
|
||||
if (isImplicitCell || isStopFrame) return;
|
||||
|
||||
// draw level name
|
||||
if (showLevelName &&
|
||||
(!sameLevel ||
|
||||
(!sameLevel || (row > 0 && xsh->isImplicitCell(row - 1, col)) ||
|
||||
(isAfterMarkers && !isSimpleView &&
|
||||
Preferences::instance()->isLevelNameOnEachMarkerEnabled()))) {
|
||||
std::wstring levelName = cell.m_level->getName();
|
||||
|
@ -2285,11 +2330,7 @@ void CellArea::drawSoundTextCell(QPainter &p, int row, int col) {
|
|||
drawFrameSeparator(p, row, col, false, heldFrame);
|
||||
|
||||
if (cell.isEmpty()) { // diagonal cross meaning end of level
|
||||
QColor levelEndColor = m_viewer->getTextColor();
|
||||
levelEndColor.setAlphaF(0.3);
|
||||
p.setPen(levelEndColor);
|
||||
p.drawLine(rect.topLeft(), rect.bottomRight());
|
||||
p.drawLine(rect.topRight(), rect.bottomLeft());
|
||||
drawEndOfLevelMarker(p, rect);
|
||||
|
||||
// only draw mark
|
||||
if (markId >= 0) {
|
||||
|
@ -2512,13 +2553,7 @@ void CellArea::drawSoundTextColumn(QPainter &p, int r0, int r1, int col) {
|
|||
// draw X shape after the occupied cell
|
||||
TXshCell prevCell;
|
||||
if (row > 0) prevCell = xsh->getCell(row - 1, col);
|
||||
if (!prevCell.isEmpty()) {
|
||||
QColor levelEndColor = m_viewer->getTextColor();
|
||||
levelEndColor.setAlphaF(0.3);
|
||||
p.setPen(levelEndColor);
|
||||
p.drawLine(info.rect.topLeft(), info.rect.bottomRight());
|
||||
p.drawLine(info.rect.topRight(), info.rect.bottomLeft());
|
||||
}
|
||||
if (!prevCell.isEmpty()) drawEndOfLevelMarker(p, info.rect);
|
||||
if (TApp::instance()->getCurrentFrame()->isEditingScene() &&
|
||||
!m_viewer->orientation()->isVerticalTimeline() &&
|
||||
row == m_viewer->getCurrentRow() &&
|
||||
|
@ -2687,6 +2722,8 @@ void CellArea::drawPaletteCell(QPainter &p, int row, int col,
|
|||
|
||||
TCellSelection *cellSelection = m_viewer->getCellSelection();
|
||||
bool isSelected = cellSelection->isCellSelected(row, col);
|
||||
bool isImplicitCell = xsh->isImplicitCell(row, col);
|
||||
bool isStopFrame = isImplicitCell ? false : cell.getFrameId().isStopFrame();
|
||||
|
||||
if (row > 0) prevCell = xsh->getCell(row - 1, col);
|
||||
TXshCell nextCell = xsh->getCell(row + 1, col);
|
||||
|
@ -2722,7 +2759,9 @@ void CellArea::drawPaletteCell(QPainter &p, int row, int col,
|
|||
cellRect.adjust(0, 0, -frameAdj.x(), -frameAdj.y());
|
||||
QRect rect = cellRect.adjusted(
|
||||
1, 1,
|
||||
(!m_viewer->orientation()->isVerticalTimeline() && !nextCell.isEmpty()
|
||||
(!m_viewer->orientation()->isVerticalTimeline() && !nextCell.isEmpty() &&
|
||||
!xsh->isImplicitCell(row + 1, col) &&
|
||||
!nextCell.getFrameId().isStopFrame()
|
||||
? 2
|
||||
: 0),
|
||||
0);
|
||||
|
@ -2758,15 +2797,14 @@ void CellArea::drawPaletteCell(QPainter &p, int row, int col,
|
|||
}
|
||||
|
||||
bool heldFrame = (!o->isVerticalTimeline() && !isAfterMarkers && sameLevel &&
|
||||
prevCell.m_frameId == cell.m_frameId);
|
||||
prevCell.m_frameId == cell.m_frameId) &&
|
||||
!isImplicitCell;
|
||||
drawFrameSeparator(p, row, col, false, heldFrame);
|
||||
|
||||
if (cell.isEmpty()) { // this means the former is not empty
|
||||
QColor levelEndColor = m_viewer->getTextColor();
|
||||
levelEndColor.setAlphaF(0.3);
|
||||
p.setPen(levelEndColor);
|
||||
p.drawLine(rect.topLeft(), rect.bottomRight());
|
||||
p.drawLine(rect.topRight(), rect.bottomLeft());
|
||||
// Implicit holds use Stop Frame Hold to denote end of level
|
||||
if (!Preferences::instance()->isImplicitHoldEnabled())
|
||||
drawEndOfLevelMarker(p, rect);
|
||||
|
||||
// only draw mark
|
||||
if (markId >= 0) {
|
||||
|
@ -2780,12 +2818,6 @@ void CellArea::drawPaletteCell(QPainter &p, int row, int col,
|
|||
Preferences::instance()->isCurrentTimelineIndicatorEnabled())
|
||||
drawCurrentTimeIndicator(p, xy);
|
||||
|
||||
// only draw mark
|
||||
if (markId >= 0) {
|
||||
p.setBrush(markColor);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawEllipse(markRect);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2798,6 +2830,8 @@ void CellArea::drawPaletteCell(QPainter &p, int row, int col,
|
|||
cellColor = (isSelected) ? m_viewer->getSelectedPaletteColumnColor()
|
||||
: m_viewer->getPaletteColumnColor();
|
||||
sideColor = m_viewer->getPaletteColumnBorderColor();
|
||||
if (isImplicitCell) cellColor.setAlpha(m_viewer->getImplicitCellAlpha());
|
||||
if (isStopFrame) cellColor.setAlpha(0);
|
||||
}
|
||||
|
||||
// paint cell
|
||||
|
@ -2809,26 +2843,31 @@ void CellArea::drawPaletteCell(QPainter &p, int row, int col,
|
|||
else
|
||||
p.fillRect(rect, QBrush(cellColor));
|
||||
|
||||
// Implicit holds use Stop Frame Hold to denote end of level
|
||||
if (isStopFrame) drawEndOfLevelMarker(p, rect, true);
|
||||
|
||||
if (TApp::instance()->getCurrentFrame()->isEditingScene() &&
|
||||
!m_viewer->orientation()->isVerticalTimeline() &&
|
||||
row == m_viewer->getCurrentRow() &&
|
||||
Preferences::instance()->isCurrentTimelineIndicatorEnabled())
|
||||
drawCurrentTimeIndicator(p, xy);
|
||||
|
||||
drawDragHandle(p, xy, sideColor);
|
||||
bool isLastRow = nextCell.isEmpty() ||
|
||||
cell.m_level.getPointer() != nextCell.m_level.getPointer();
|
||||
drawEndOfDragHandle(p, isLastRow, xy, cellColor);
|
||||
drawLockedDottedLine(p, xsh->getColumn(col)->isLocked(), xy, cellColor);
|
||||
if (!isImplicitCell) {
|
||||
drawDragHandle(p, xy, sideColor);
|
||||
bool isLastRow = nextCell.isEmpty() ||
|
||||
cell.m_level.getPointer() != nextCell.m_level.getPointer();
|
||||
drawEndOfDragHandle(p, isLastRow, xy, cellColor);
|
||||
drawLockedDottedLine(p, xsh->getColumn(col)->isLocked(), xy, cellColor);
|
||||
}
|
||||
|
||||
if (o->isVerticalTimeline() && isAfterMarkers) {
|
||||
p.setPen(m_viewer->getMarkerLineColor());
|
||||
p.drawLine(o->line(PredefinedLine::SEE_MARKER_THROUGH).translated(xy));
|
||||
}
|
||||
|
||||
if (sameLevel && prevCell.m_frameId == cell.m_frameId &&
|
||||
!isAfterMarkers) { // cell equal to previous one (not on marker line):
|
||||
// do not write anything and draw a vertical line
|
||||
if ((sameLevel && prevCell.m_frameId == cell.m_frameId && !isAfterMarkers) ||
|
||||
isImplicitCell) { // cell equal to previous one (not on marker line):
|
||||
// do not write anything and draw a vertical line
|
||||
if (o->isVerticalTimeline()) {
|
||||
QPen oldPen = p.pen();
|
||||
p.setPen(QPen(m_viewer->getTextColor(), 1));
|
||||
|
@ -2852,7 +2891,8 @@ void CellArea::drawPaletteCell(QPainter &p, int row, int col,
|
|||
TStageObject *pegbar = xsh->getStageObject(m_viewer->getObjectId(col));
|
||||
if (pegbar->isKeyframe(row)) return;
|
||||
}
|
||||
drawFrameMarker(p, QPoint(x, y), (isRed ? Qt::red : Qt::black));
|
||||
if (!isStopFrame)
|
||||
drawFrameMarker(p, QPoint(x, y), (isRed ? Qt::red : Qt::black));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2905,10 +2945,15 @@ void CellArea::drawPaletteCell(QPainter &p, int row, int col,
|
|||
} else {
|
||||
QString frameNumber("");
|
||||
// set number
|
||||
if (fid.getNumber() > 0) frameNumber = QString::number(fid.getNumber());
|
||||
if (fid.isStopFrame())
|
||||
frameNumber = "";
|
||||
else if (fid.getNumber() > 0)
|
||||
frameNumber = QString::number(fid.getNumber());
|
||||
// add letter
|
||||
if (!fid.getLetter().isEmpty()) frameNumber += fid.getLetter();
|
||||
p.drawText(nameRect, Qt::AlignRight | Qt::AlignBottom, frameNumber);
|
||||
int alignFlag = (!fid.isStopFrame() ? Qt::AlignRight | Qt::AlignBottom
|
||||
: Qt::AlignCenter);
|
||||
p.drawText(nameRect, alignFlag, frameNumber);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2970,9 +3015,9 @@ void CellArea::drawKeyframe(QPainter &p, const QRect toBeUpdated) {
|
|||
row0 = std::max(row0, r0);
|
||||
row1 = std::min(row1, r1);
|
||||
|
||||
QRect tmpKeyRect = (col >= 0) ? keyRect
|
||||
: o->rect(PredefinedRect::CAMERA_KEY_ICON)
|
||||
.translated(-frameAdj / 2);
|
||||
QRect tmpKeyRect =
|
||||
(col >= 0) ? keyRect : o->rect(PredefinedRect::CAMERA_KEY_ICON)
|
||||
.translated(-frameAdj / 2);
|
||||
|
||||
/*- first, draw key segments -*/
|
||||
p.setPen(m_viewer->getTextColor());
|
||||
|
@ -3443,7 +3488,8 @@ void CellArea::mousePressEvent(QMouseEvent *event) {
|
|||
m_viewer->getKeyframeSelection()->selectNone();
|
||||
setDragTool(
|
||||
XsheetGUI::DragTool::makeLevelExtenderTool(m_viewer, false, true));
|
||||
} else if ((!xsh->getCell(row, col).isEmpty()) &&
|
||||
} else if ((!xsh->getCell(row, col).isEmpty() &&
|
||||
!xsh->isImplicitCell(row, col)) &&
|
||||
o->rect(PredefinedRect::DRAG_AREA)
|
||||
.adjusted(0, 0, -frameAdj.x(), -frameAdj.y())
|
||||
.contains(mouseInCell)) {
|
||||
|
@ -3714,7 +3760,7 @@ void CellArea::contextMenuEvent(QContextMenuEvent *event) {
|
|||
int row = cellPosition.frame();
|
||||
int col = cellPosition.layer();
|
||||
TXshCell cell = m_viewer->getXsheet()->getCell(row, col);
|
||||
|
||||
bool isImplicitCell = m_viewer->getXsheet()->isImplicitCell(row, col);
|
||||
QMenu menu(this);
|
||||
|
||||
// Verifico se ho cliccato su una nota
|
||||
|
@ -3783,13 +3829,13 @@ void CellArea::contextMenuEvent(QContextMenuEvent *event) {
|
|||
}
|
||||
if (areCellsEmpty) break;
|
||||
}
|
||||
createCellMenu(menu, areCellsEmpty, cell, row, col);
|
||||
createCellMenu(menu, areCellsEmpty, cell, row, col, isImplicitCell);
|
||||
} else {
|
||||
m_viewer->getCellSelection()->makeCurrent();
|
||||
m_viewer->getCellSelection()->selectCell(row, col);
|
||||
m_viewer->setCurrentColumn(col);
|
||||
|
||||
createCellMenu(menu, !cell.isEmpty(), cell, row, col);
|
||||
createCellMenu(menu, !cell.isEmpty(), cell, row, col, isImplicitCell);
|
||||
}
|
||||
|
||||
if (!menu.isEmpty()) menu.exec(event->globalPos());
|
||||
|
@ -3879,7 +3925,7 @@ const bool CellArea::isControlPressed() { return isCtrlPressed; }
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CellArea::createCellMenu(QMenu &menu, bool isCellSelected, TXshCell cell,
|
||||
int row, int col) {
|
||||
int row, int col, bool isImplicitCell) {
|
||||
CommandManager *cmdManager = CommandManager::instance();
|
||||
|
||||
bool soundCellsSelected = m_viewer->areSoundCellsSelected();
|
||||
|
@ -3952,11 +3998,13 @@ void CellArea::createCellMenu(QMenu &menu, bool isCellSelected, TXshCell cell,
|
|||
}
|
||||
menu.addMenu(editCellNumbersMenu);
|
||||
}
|
||||
|
||||
menu.addAction(cmdManager->getAction(MI_FillEmptyCell));
|
||||
menu.addAction(cmdManager->getAction(MI_StopFrameHold));
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
if (!soundTextCellsSelected)
|
||||
if (!soundTextCellsSelected && !isImplicitCell)
|
||||
menu.addAction(cmdManager->getAction(MI_Autorenumber));
|
||||
}
|
||||
|
||||
|
@ -3997,17 +4045,19 @@ void CellArea::createCellMenu(QMenu &menu, bool isCellSelected, TXshCell cell,
|
|||
replaceMenu->addAction(tmpAction);
|
||||
}
|
||||
}
|
||||
if (!soundCellsSelected && !soundTextCellsSelected) {
|
||||
if (selectionContainTlvImage(m_viewer->getCellSelection(),
|
||||
m_viewer->getXsheet()))
|
||||
replaceLevelMenu->addAction(
|
||||
cmdManager->getAction(MI_RevertToCleanedUp));
|
||||
if (selectionContainLevelImage(m_viewer->getCellSelection(),
|
||||
m_viewer->getXsheet()))
|
||||
replaceLevelMenu->addAction(
|
||||
cmdManager->getAction(MI_RevertToLastSaved));
|
||||
}
|
||||
}
|
||||
|
||||
if (!soundCellsSelected && !soundTextCellsSelected) {
|
||||
if (selectionContainTlvImage(m_viewer->getCellSelection(),
|
||||
m_viewer->getXsheet()))
|
||||
replaceLevelMenu->addAction(
|
||||
cmdManager->getAction(MI_RevertToCleanedUp));
|
||||
if (selectionContainLevelImage(m_viewer->getCellSelection(),
|
||||
m_viewer->getXsheet()))
|
||||
replaceLevelMenu->addAction(
|
||||
cmdManager->getAction(MI_RevertToLastSaved));
|
||||
menu.addAction(cmdManager->getAction(MI_SetKeyframes));
|
||||
menu.addAction(cmdManager->getAction(MI_ShiftKeyframesDown));
|
||||
menu.addAction(cmdManager->getAction(MI_ShiftKeyframesUp));
|
||||
|
@ -4015,8 +4065,10 @@ void CellArea::createCellMenu(QMenu &menu, bool isCellSelected, TXshCell cell,
|
|||
menu.addSeparator();
|
||||
}
|
||||
|
||||
menu.addAction(cmdManager->getAction(MI_Cut));
|
||||
menu.addAction(cmdManager->getAction(MI_Copy));
|
||||
if (!isImplicitCell) {
|
||||
menu.addAction(cmdManager->getAction(MI_Cut));
|
||||
menu.addAction(cmdManager->getAction(MI_Copy));
|
||||
}
|
||||
menu.addAction(cmdManager->getAction(MI_Paste));
|
||||
|
||||
QMenu *pasteSpecialMenu = new QMenu(tr("Paste Special"), this);
|
||||
|
@ -4029,7 +4081,7 @@ void CellArea::createCellMenu(QMenu &menu, bool isCellSelected, TXshCell cell,
|
|||
}
|
||||
menu.addMenu(pasteSpecialMenu);
|
||||
|
||||
menu.addAction(cmdManager->getAction(MI_Clear));
|
||||
if (!isImplicitCell) menu.addAction(cmdManager->getAction(MI_Clear));
|
||||
menu.addAction(cmdManager->getAction(MI_Insert));
|
||||
if (!soundTextCellsSelected) {
|
||||
menu.addAction(cmdManager->getAction(MI_CreateBlankDrawing));
|
||||
|
@ -4086,6 +4138,7 @@ void CellArea::createCellMenu(QMenu &menu, bool isCellSelected, TXshCell cell,
|
|||
menu.addAction(cmdManager->getAction(MI_CreateBlankDrawing));
|
||||
menu.addSeparator();
|
||||
menu.addAction(cmdManager->getAction(MI_FillEmptyCell));
|
||||
menu.addAction(cmdManager->getAction(MI_StopFrameHold));
|
||||
if (cameraCellsSelected) {
|
||||
menu.addSeparator();
|
||||
menu.addAction(cmdManager->getAction(MI_SetKeyframes));
|
||||
|
@ -4131,6 +4184,7 @@ void CellArea::createCellMenu(QMenu &menu, bool isCellSelected, TXshCell cell,
|
|||
menu.addAction(cmdManager->getAction(MI_ToggleAutoCreate));
|
||||
menu.addAction(cmdManager->getAction(MI_ToggleCreationInHoldCells));
|
||||
menu.addAction(cmdManager->getAction(MI_ToggleAutoStretch));
|
||||
menu.addAction(cmdManager->getAction(MI_ToggleImplicitHold));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -4160,7 +4214,7 @@ void CellArea::onReplaceByCastedLevel(QAction *action) {
|
|||
if (!cell.m_level.getPointer() || cell.m_level.getPointer() == level)
|
||||
continue;
|
||||
|
||||
TXshCell oldCell = cell;
|
||||
TXshCell oldCell = xsh->isImplicitCell(r, c) ? TXshCell() : cell;
|
||||
|
||||
cell.m_level = TXshLevelP(level);
|
||||
xsh->setCell(r, c, cell);
|
||||
|
|
|
@ -131,6 +131,7 @@ class CellArea final : public QWidget {
|
|||
|
||||
void drawFrameMarker(QPainter &p, const QPoint &xy, QColor color,
|
||||
bool isKeyFrame = false, bool isCamera = false);
|
||||
void drawEndOfLevelMarker(QPainter &p, QRect rect, bool isStopFrame = false);
|
||||
|
||||
// Restistusce true
|
||||
bool getEaseHandles(int r0, int r1, double e0, double e1, int &rh0, int &rh1);
|
||||
|
@ -183,7 +184,7 @@ protected:
|
|||
cella,
|
||||
distinguendo i due casi: cella piena, cella vuota.*/
|
||||
void createCellMenu(QMenu &menu, bool isCellSelected, TXshCell cell, int row,
|
||||
int col);
|
||||
int col, bool isImplicitCell);
|
||||
//! Crea il menu' del tasto destro che si visualizza si clicca su un key
|
||||
//! frame.
|
||||
void createKeyMenu(QMenu &menu);
|
||||
|
|
|
@ -102,7 +102,7 @@ bool containsRasterLevel(TColumnSelection *selection) {
|
|||
if (!cellCol) continue;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < cellCol->getMaxFrame() + 1; i++) {
|
||||
for (i = 0; i < cellCol->getMaxFrame(true) + 1; i++) {
|
||||
TXshCell cell = cellCol->getCell(i);
|
||||
if (cell.isEmpty()) continue;
|
||||
TXshSimpleLevel *level = cell.getSimpleLevel();
|
||||
|
|
|
@ -169,7 +169,10 @@ void InsertSceneFrameUndo::doInsertSceneFrame(int frame) {
|
|||
objectId = TStageObjectId::ColumnId(c);
|
||||
|
||||
xsh->insertCells(frame, c);
|
||||
xsh->setCell(frame, c, xsh->getCell(frame + 1, c));
|
||||
TXshCell cell;
|
||||
if (!Preferences::instance()->isImplicitHoldEnabled() && frame > 0)
|
||||
cell = xsh->getCell(frame - 1, c);
|
||||
xsh->setCell(frame, c, cell);
|
||||
}
|
||||
|
||||
if (!xsh->getColumn(c) || xsh->getColumn(c)->isLocked()) continue;
|
||||
|
@ -288,6 +291,24 @@ public:
|
|||
}
|
||||
} ToggleAutoStretchCommand;
|
||||
|
||||
//=============================================================================
|
||||
|
||||
class ToggleImplicitHoldCommand final : public MenuItemHandler {
|
||||
public:
|
||||
ToggleImplicitHoldCommand() : MenuItemHandler(MI_ToggleImplicitHold) {}
|
||||
void execute() override {
|
||||
bool currentImplicitHoldEnabled =
|
||||
Preferences::instance()->isImplicitHoldEnabled();
|
||||
if (CommandManager::instance()
|
||||
->getAction(MI_ToggleImplicitHold)
|
||||
->isChecked() == currentImplicitHoldEnabled)
|
||||
return;
|
||||
Preferences::instance()->setValue(EnableImplicitHold,
|
||||
!currentImplicitHoldEnabled);
|
||||
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
|
||||
}
|
||||
} ToggleImplicitHoldCommand;
|
||||
|
||||
//*****************************************************************************
|
||||
// RemoveSceneFrame command
|
||||
//*****************************************************************************
|
||||
|
@ -314,7 +335,8 @@ public:
|
|||
|
||||
for (int c = 0; c != colsCount; ++c) {
|
||||
// Store cell
|
||||
m_cells[c] = xsh->getCell(m_frame, c);
|
||||
const TXshCell &cell = xsh->getCell(m_frame, c);
|
||||
m_cells[c] = xsh->isImplicitCell(m_frame, c) ? TXshCell() : cell;
|
||||
|
||||
// Store stage object keyframes
|
||||
TStageObject *obj = xsh->getStageObject(TStageObjectId::ColumnId(c));
|
||||
|
@ -638,9 +660,10 @@ public:
|
|||
int r = m_range.m_r0;
|
||||
while (c <= m_range.m_c1) {
|
||||
tempCol = c;
|
||||
while (r <= m_range.m_r1) {
|
||||
while (r <= m_range.m_r1 + 1) {
|
||||
tempRow = r;
|
||||
if (xsh->getCell(tempRow, tempCol).isEmpty()) {
|
||||
if (xsh->getCell(tempRow, tempCol).isEmpty() ||
|
||||
xsh->isImplicitCell(tempRow, tempCol)) {
|
||||
emptyCells.push_back(std::make_pair(tempRow, tempCol));
|
||||
}
|
||||
r++;
|
||||
|
@ -664,7 +687,7 @@ public:
|
|||
int r = m_range.m_r0;
|
||||
while (c <= m_range.m_c1) {
|
||||
col = c;
|
||||
while (r <= m_range.m_r1) {
|
||||
while (r <= m_range.m_r1 + 1) {
|
||||
row = r;
|
||||
bool found = false;
|
||||
for (int i = 0; i < emptyCells.size(); i++) {
|
||||
|
@ -677,7 +700,7 @@ public:
|
|||
r++;
|
||||
continue;
|
||||
}
|
||||
changeDrawing(-m_direction, row, col);
|
||||
if (r <= m_range.m_r1) changeDrawing(-m_direction, row, col);
|
||||
r++;
|
||||
}
|
||||
r = m_range.m_r0;
|
||||
|
@ -698,11 +721,18 @@ public:
|
|||
int col, row;
|
||||
int c = m_range.m_c0;
|
||||
int r = m_range.m_r0;
|
||||
TXsheetP xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
|
||||
while (c <= m_range.m_c1) {
|
||||
col = c;
|
||||
// Convert implicit cell at end of selected range into a populated cell
|
||||
if (xsh->isImplicitCell((m_range.m_r1 + 1), col)) {
|
||||
TXshCell origCell = xsh->getCell((m_range.m_r1 + 1), col);
|
||||
xsh->setCell((m_range.m_r1 + 1), col, origCell);
|
||||
}
|
||||
while (r <= m_range.m_r1) {
|
||||
row = r;
|
||||
changeDrawing(m_direction, row, col);
|
||||
if (row == m_range.m_r0 || !xsh->isImplicitCell(row, col))
|
||||
changeDrawing(m_direction, row, col);
|
||||
r++;
|
||||
}
|
||||
r = m_range.m_r0;
|
||||
|
@ -766,13 +796,16 @@ public:
|
|||
|
||||
// Find the 1st populated cell in the column
|
||||
if (baseCell.isEmpty()) continue;
|
||||
if (xsh->isImplicitCell(r, c))
|
||||
emptyCells.push_back(std::make_pair(r, c));
|
||||
|
||||
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())
|
||||
if ((r + frameCount) >= xsh->getFrameCount()) break;
|
||||
if (nextCell.isEmpty() || xsh->isImplicitCell((r + frameCount), c))
|
||||
emptyCells.push_back(std::make_pair((r + frameCount), c));
|
||||
|
||||
frameCount++;
|
||||
|
@ -820,7 +853,10 @@ public:
|
|||
while (n < ct->second) {
|
||||
int row = ct->first.first + n;
|
||||
int col = ct->first.second;
|
||||
DrawingSubtitutionUndo::changeDrawing(m_direction, row, col);
|
||||
if (n == 0 ||
|
||||
!TApp::instance()->getCurrentXsheet()->getXsheet()->isImplicitCell(
|
||||
row, col))
|
||||
DrawingSubtitutionUndo::changeDrawing(m_direction, row, col);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
@ -853,10 +889,12 @@ bool DrawingSubtitutionUndo::changeDrawing(int delta, int row, int col) {
|
|||
return false;
|
||||
cell = prevCell;
|
||||
usePrevCell = true;
|
||||
} else if (!cell.m_level || !(cell.m_level->getSimpleLevel() ||
|
||||
cell.m_level->getChildLevel() ||
|
||||
cell.m_level->getSoundTextLevel()))
|
||||
} else if (cell.getFrameId().isStopFrame() || !cell.m_level ||
|
||||
!(cell.m_level->getSimpleLevel() ||
|
||||
cell.m_level->getChildLevel() ||
|
||||
cell.m_level->getSoundTextLevel()))
|
||||
return false;
|
||||
|
||||
TXshLevel *level = cell.m_level->getSimpleLevel();
|
||||
if (!level) level = cell.m_level->getChildLevel();
|
||||
if (!level) level = cell.m_level->getSoundTextLevel();
|
||||
|
@ -2316,11 +2354,10 @@ public:
|
|||
|
||||
while (!exit) {
|
||||
TXshCell cell = TApp::instance()->getCurrentXsheetViewer()->getXsheet()->getCell(currentPos, column);
|
||||
if (cell.isEmpty()) {
|
||||
if (cell.isEmpty() || cell.getFrameId().isStopFrame()) {
|
||||
(direction == up) ? currentPos++ : currentPos--;
|
||||
exit = true;
|
||||
}
|
||||
else
|
||||
} else
|
||||
(direction == up) ? currentPos-- : currentPos++;
|
||||
}
|
||||
|
||||
|
@ -2328,15 +2365,19 @@ public:
|
|||
}
|
||||
|
||||
void execute() override {
|
||||
int col = TApp::instance()->getCurrentColumn()->getColumnIndex();
|
||||
int row = TApp::instance()->getCurrentFrame()->getFrame();
|
||||
TXshCell cell =
|
||||
TApp::instance()->getCurrentXsheetViewer()->getXsheet()->getCell(row, col);
|
||||
if (cell.isEmpty()) return;
|
||||
int col = TApp::instance()->getCurrentColumn()->getColumnIndex();
|
||||
int row = TApp::instance()->getCurrentFrame()->getFrame();
|
||||
TXsheet *xsh = TApp::instance()->getCurrentXsheetViewer()->getXsheet();
|
||||
TXshCell cell = xsh->getCell(row, col);
|
||||
if (cell.isEmpty() || cell.getFrameId().isStopFrame()) return;
|
||||
int step, r0, r1;
|
||||
|
||||
xsh->getCellRange(col, r0, r1);
|
||||
|
||||
int top = getNonEmptyCell(row, col, Direction::up);
|
||||
int bottom = getNonEmptyCell(row, col, Direction::down);
|
||||
int bottom = (xsh->isImplicitCell(row, col) && row > r1)
|
||||
? row
|
||||
: getNonEmptyCell(row, col, Direction::down);
|
||||
|
||||
XsheetGUI::getPlayRange(r0, r1, step);
|
||||
XsheetGUI::setPlayRange(top, bottom, step);
|
||||
|
|
|
@ -2063,7 +2063,8 @@ protected:
|
|||
getViewer()->orientation()->isVerticalTimeline());
|
||||
for (c = col; c < rect.getLx() + col; c++) {
|
||||
for (r = row; r < rect.getLy() + row; r++)
|
||||
if (!xsh->getCell(r, c).isEmpty()) return false;
|
||||
if (!xsh->getCell(r, c).isEmpty() && !xsh->isImplicitCell(r, c))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -349,6 +349,11 @@ class XsheetViewer final : public QFrame, public SaveLoadQSettings {
|
|||
Q_PROPERTY(QColor SelectedMeshColumnColor READ getSelectedMeshColumnColor
|
||||
WRITE setSelectedMeshColumnColor)
|
||||
|
||||
// Implicit Cell alpha
|
||||
int m_implicitCellAlpha;
|
||||
Q_PROPERTY(int ImplicitCellAlpha READ getImplicitCellAlpha WRITE
|
||||
setImplicitCellAlpha);
|
||||
|
||||
// Table color
|
||||
QColor m_tableColor;
|
||||
Q_PROPERTY(QColor TableColor READ getTableColor WRITE setTableColor)
|
||||
|
@ -949,6 +954,10 @@ public:
|
|||
return m_selectedMeshColumnColor;
|
||||
}
|
||||
|
||||
// Implicit Cell Alpha
|
||||
void setImplicitCellAlpha(const int &alpha) { m_implicitCellAlpha = alpha; }
|
||||
int getImplicitCellAlpha() const { return m_implicitCellAlpha; }
|
||||
|
||||
// Table node
|
||||
void setTableColor(const QColor &color) { m_tableColor = color; }
|
||||
QColor getTableColor() const { return m_tableColor; }
|
||||
|
|
|
@ -1272,7 +1272,7 @@ void RowArea::contextMenuEvent(QContextMenuEvent *event) {
|
|||
bool RowArea::canSetAutoMarkers() {
|
||||
TXshCell cell =
|
||||
m_viewer->getXsheet()->getCell(m_row, m_viewer->getCurrentColumn());
|
||||
return cell.isEmpty() ? false : true;
|
||||
return cell.isEmpty() || cell.getFrameId().isStopFrame() ? false : true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "toonz/tfxhandle.h"
|
||||
#include "toonz/tcolumnhandle.h"
|
||||
#include "toonz/tscenehandle.h"
|
||||
#include "toonz/preferences.h"
|
||||
#include "historytypes.h"
|
||||
|
||||
// TnzBase includes
|
||||
|
@ -309,7 +310,9 @@ TXshZeraryFxColumn *FxCommandUndo::createZeraryFxColumn(TXsheet *xsh, TFx *zfx,
|
|||
int frameCount = xsh->getScene()->getFrameCount() - row;
|
||||
|
||||
TXshZeraryFxColumn *column =
|
||||
new TXshZeraryFxColumn(frameCount > 0 ? frameCount : 100);
|
||||
new TXshZeraryFxColumn(Preferences::instance()->isImplicitHoldEnabled()
|
||||
? 1
|
||||
: (frameCount > 0 ? frameCount : 100));
|
||||
column->getZeraryColumnFx()->setZeraryFx(zfx);
|
||||
column->insertEmptyCells(0, row);
|
||||
|
||||
|
@ -2541,7 +2544,9 @@ void UndoPasteFxs::initialize(const std::map<TFx *, int> &zeraryFxColumnSize,
|
|||
// column with
|
||||
// the specified column size
|
||||
std::map<TFx *, int>::const_iterator it = zeraryFxColumnSize.find(fx);
|
||||
int rows = (it == zeraryFxColumnSize.end()) ? 100 : it->second;
|
||||
int rows = Preferences::instance()->isImplicitHoldEnabled()
|
||||
? 1
|
||||
: ((it == zeraryFxColumnSize.end()) ? 100 : it->second);
|
||||
|
||||
TXshZeraryFxColumn *column = new TXshZeraryFxColumn(rows);
|
||||
TZeraryColumnFx *zcfx = column->getZeraryColumnFx();
|
||||
|
|
|
@ -512,7 +512,8 @@ void Preferences::definePreferenceItems() {
|
|||
|
||||
define(EnableAutocreation, "EnableAutocreation", QMetaType::Bool, true);
|
||||
define(NumberingSystem, "NumberingSystem", QMetaType::Int, 0); // Incremental
|
||||
define(EnableAutoStretch, "EnableAutoStretch", QMetaType::Bool, true);
|
||||
define(EnableAutoStretch, "EnableAutoStretch", QMetaType::Bool, false);
|
||||
define(EnableImplicitHold, "EnableImplicitHold", QMetaType::Bool, true);
|
||||
define(EnableCreationInHoldCells, "EnableCreationInHoldCells",
|
||||
QMetaType::Bool, true);
|
||||
define(EnableAutoRenumber, "EnableAutoRenumber", QMetaType::Bool, true);
|
||||
|
|
|
@ -111,6 +111,15 @@ public:
|
|||
if (!m_cellColumn) return m_frame;
|
||||
TXshCell cell = m_cellColumn->getCell(tfloor(frame));
|
||||
assert(!cell.isEmpty());
|
||||
if (cell.isEmpty() && Preferences::instance()->isImplicitHoldEnabled()) {
|
||||
int r0, r1;
|
||||
m_cellColumn->getRange(r0, r1);
|
||||
for (int r = std::min(r1, frame); r >= r0; r--) {
|
||||
cell = m_cellColumn->getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cell.m_frameId.getNumber() - 1;
|
||||
}
|
||||
|
||||
|
@ -801,6 +810,15 @@ PlacedFx FxBuilder::makePF(TLevelColumnFx *lcfx) {
|
|||
// Retrieve the corresponding xsheet cell to build up
|
||||
/*-- 現在のフレームのセルを取得 --*/
|
||||
TXshCell cell = lcfx->getColumn()->getCell(tfloor(m_frame));
|
||||
if (cell.isEmpty() && Preferences::instance()->isImplicitHoldEnabled()) {
|
||||
int r0, r1;
|
||||
lcfx->getColumn()->getRange(r0, r1);
|
||||
for (int r = std::min(r1, tfloor(m_frame)); r >= r0; r--) {
|
||||
cell = lcfx->getColumn()->getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int levelFrame = cell.m_frameId.getNumber() - 1;
|
||||
|
||||
/*-- ParticlesFxに繋がっておらず、空セルの場合は 中身無しを返す --*/
|
||||
|
@ -940,7 +958,17 @@ PlacedFx FxBuilder::makePF(TPaletteColumnFx *pcfx) {
|
|||
if (!pcfx->getColumn()->isPreviewVisible()) return PlacedFx();
|
||||
|
||||
TXshCell cell = pcfx->getColumn()->getCell(tfloor(m_frame));
|
||||
if (cell.isEmpty()) return PlacedFx();
|
||||
if (cell.isEmpty() && Preferences::instance()->isImplicitHoldEnabled()) {
|
||||
int r0, r1;
|
||||
pcfx->getColumn()->getRange(r0, r1);
|
||||
for (int r = std::min(r1, tfloor(m_frame)); r >= r0; r--) {
|
||||
cell = pcfx->getColumn()->getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cell.isEmpty() || cell.getFrameId().isStopFrame()) return PlacedFx();
|
||||
|
||||
PlacedFx pf;
|
||||
pf.m_columnIndex = pcfx->getColumn()->getIndex();
|
||||
|
@ -968,6 +996,15 @@ PlacedFx FxBuilder::makePF(TZeraryColumnFx *zcfx) {
|
|||
return PlacedFx();
|
||||
|
||||
TXshCell cell = zcfx->getColumn()->getCell(tfloor(m_frame));
|
||||
if (cell.isEmpty() && Preferences::instance()->isImplicitHoldEnabled()) {
|
||||
int r0, r1;
|
||||
zcfx->getColumn()->getRange(r0, r1);
|
||||
for (int r = std::min(r1, tfloor(m_frame)); r >= r0; r--) {
|
||||
cell = zcfx->getColumn()->getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Build
|
||||
PlacedFx pf;
|
||||
|
@ -978,7 +1015,7 @@ PlacedFx FxBuilder::makePF(TZeraryColumnFx *zcfx) {
|
|||
return PlacedFx();
|
||||
|
||||
// if the cell is empty, only inherits its placement
|
||||
if (cell.isEmpty()) return pf;
|
||||
if (cell.isEmpty() || cell.getFrameId().isStopFrame()) return pf;
|
||||
|
||||
// set m_fx only when the current cell is not empty
|
||||
pf.m_fx =
|
||||
|
|
|
@ -364,22 +364,23 @@ void StageBuilder::addCell(PlayerSet &players, ToonzScene *scene, TXsheet *xsh,
|
|||
double columnZ = pegbar->getZ(row);
|
||||
double columnNoScaleZ = pegbar->getGlobalNoScaleZ();
|
||||
|
||||
TXshCell cell = xsh->getCell(row, col);
|
||||
TXshLevel *xl = cell.m_level.getPointer();
|
||||
TXshCell cell = xsh->getCell(row, col);
|
||||
TXshLevel *xl = cell.m_level.getPointer();
|
||||
TXshSimpleLevel *sl = xl ? xl->getSimpleLevel() : 0;
|
||||
// check the previous row for a stop motion layer
|
||||
if (!xl) {
|
||||
// Get the last populated cell
|
||||
cell = xsh->getCell(row - 1, col);
|
||||
xl = cell.m_level.getPointer();
|
||||
if (!xl) {
|
||||
|
||||
if (!xl) return;
|
||||
|
||||
sl = xl->getSimpleLevel();
|
||||
|
||||
if (sl && m_liveViewImage && sl == m_liveViewPlayer.m_sl)
|
||||
row -= 1;
|
||||
else
|
||||
return;
|
||||
} else {
|
||||
xl = cell.m_level.getPointer();
|
||||
TXshSimpleLevel *sl = xl->getSimpleLevel();
|
||||
if (sl && m_liveViewImage && sl == m_liveViewPlayer.m_sl) {
|
||||
row -= 1;
|
||||
} else
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ZPlacement cameraPlacement;
|
||||
|
@ -394,8 +395,6 @@ void StageBuilder::addCell(PlayerSet &players, ToonzScene *scene, TXsheet *xsh,
|
|||
|
||||
if (!columnBehindCamera) return;
|
||||
|
||||
TXshSimpleLevel *sl = xl->getSimpleLevel();
|
||||
|
||||
bool storePlayer =
|
||||
sl || (xl->getChildLevel() &&
|
||||
locals::applyPlasticDeform(column.getPointer(), m_vs) &&
|
||||
|
|
|
@ -819,7 +819,17 @@ bool TLevelColumnFx::canHandle(const TRenderSettings &info, double frame) {
|
|||
|
||||
if (!m_levelColumn) return true;
|
||||
|
||||
TXshCell cell = m_levelColumn->getCell(m_levelColumn->getFirstRow());
|
||||
int row = m_levelColumn->getFirstRow();
|
||||
TXshCell cell = m_levelColumn->getCell(row);
|
||||
if (cell.isEmpty() && Preferences::instance()->isImplicitHoldEnabled()) {
|
||||
int r0, r1;
|
||||
m_levelColumn->getRange(r0, r1);
|
||||
for (int r = std::min(r1, row); r >= r0; r--) {
|
||||
cell = m_levelColumn->getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cell.isEmpty()) return true;
|
||||
|
||||
TXshSimpleLevel *sl = cell.m_level->getSimpleLevel();
|
||||
|
@ -835,7 +845,17 @@ TAffine TLevelColumnFx::handledAffine(const TRenderSettings &info,
|
|||
double frame) {
|
||||
if (!m_levelColumn) return TAffine();
|
||||
|
||||
TXshCell cell = m_levelColumn->getCell(m_levelColumn->getFirstRow());
|
||||
int row = m_levelColumn->getFirstRow();
|
||||
TXshCell cell = m_levelColumn->getCell(row);
|
||||
if (cell.isEmpty() && Preferences::instance()->isImplicitHoldEnabled()) {
|
||||
int r0, r1;
|
||||
m_levelColumn->getRange(r0, r1);
|
||||
for (int r = std::min(r1, row); r >= r0; r--) {
|
||||
cell = m_levelColumn->getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cell.isEmpty()) return TAffine();
|
||||
|
||||
TXshSimpleLevel *sl = cell.m_level->getSimpleLevel();
|
||||
|
@ -873,6 +893,16 @@ TFilePath TLevelColumnFx::getPalettePath(int frame) const {
|
|||
if (!m_levelColumn) return TFilePath();
|
||||
|
||||
TXshCell cell = m_levelColumn->getCell(frame);
|
||||
if (cell.isEmpty() && Preferences::instance()->isImplicitHoldEnabled()) {
|
||||
int r0, r1;
|
||||
m_levelColumn->getRange(r0, r1);
|
||||
for (int r = std::min(r1, frame); r >= r0; r--) {
|
||||
cell = m_levelColumn->getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cell.isEmpty()) return TFilePath();
|
||||
|
||||
TXshSimpleLevel *sl = cell.m_level->getSimpleLevel();
|
||||
|
@ -894,6 +924,15 @@ TPalette *TLevelColumnFx::getPalette(int frame) const {
|
|||
if (!m_levelColumn) return 0;
|
||||
|
||||
TXshCell cell = m_levelColumn->getCell(frame);
|
||||
if (cell.isEmpty() && Preferences::instance()->isImplicitHoldEnabled()) {
|
||||
int r0, r1;
|
||||
m_levelColumn->getRange(r0, r1);
|
||||
for (int r = std::min(r1, frame); r >= r0; r--) {
|
||||
cell = m_levelColumn->getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cell.isEmpty()) return 0;
|
||||
|
||||
TXshSimpleLevel *sl = cell.m_level->getSimpleLevel();
|
||||
|
@ -921,6 +960,15 @@ void TLevelColumnFx::doDryCompute(TRectD &rect, double frame,
|
|||
|
||||
int row = (int)frame;
|
||||
TXshCell cell = m_levelColumn->getCell(row);
|
||||
if (cell.isEmpty() && Preferences::instance()->isImplicitHoldEnabled()) {
|
||||
int r0, r1;
|
||||
m_levelColumn->getRange(r0, r1);
|
||||
for (int r = std::min(r1, row); r >= r0; r--) {
|
||||
cell = m_levelColumn->getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cell.isEmpty()) return;
|
||||
|
||||
TXshSimpleLevel *sl = cell.m_level->getSimpleLevel();
|
||||
|
@ -971,7 +1019,15 @@ void TLevelColumnFx::doCompute(TTile &tile, double frame,
|
|||
// Ensure that a corresponding cell and level exists
|
||||
int row = (int)frame;
|
||||
TXshCell cell = m_levelColumn->getCell(row);
|
||||
|
||||
if (cell.isEmpty() && Preferences::instance()->isImplicitHoldEnabled()) {
|
||||
int r0, r1;
|
||||
m_levelColumn->getRange(r0, r1);
|
||||
for (int r = std::min(r1, row); r >= r0; r--) {
|
||||
cell = m_levelColumn->getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cell.isEmpty()) return;
|
||||
|
||||
TXshSimpleLevel *sl = cell.m_level->getSimpleLevel();
|
||||
|
@ -1388,8 +1444,17 @@ bool TLevelColumnFx::doGetBBox(double frame, TRectD &bBox,
|
|||
// Usual preliminaries (make sure a level/cell exists, etc...)
|
||||
if (!m_levelColumn) return false;
|
||||
|
||||
int row = (int)frame;
|
||||
const TXshCell &cell = m_levelColumn->getCell(row);
|
||||
int row = (int)frame;
|
||||
TXshCell cell = m_levelColumn->getCell(row);
|
||||
if (cell.isEmpty() && Preferences::instance()->isImplicitHoldEnabled()) {
|
||||
int r0, r1;
|
||||
m_levelColumn->getRange(r0, r1);
|
||||
for (int r = std::min(r1, row); r >= r0; r--) {
|
||||
cell = m_levelColumn->getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cell.isEmpty()) return false;
|
||||
|
||||
TXshLevelP xshl = cell.m_level;
|
||||
|
@ -1418,7 +1483,17 @@ bool TLevelColumnFx::doGetBBox(double frame, TRectD &bBox,
|
|||
|
||||
dpi = imageInfo.m_dpix / Stage::inch;
|
||||
} else {
|
||||
TImageP img = m_levelColumn->getCell(row).getImage(false);
|
||||
TXshCell cell = m_levelColumn->getCell(row);
|
||||
if (cell.isEmpty() && Preferences::instance()->isImplicitHoldEnabled()) {
|
||||
int r0, r1;
|
||||
m_levelColumn->getRange(r0, r1);
|
||||
for (int r = std::min(r1, row); r >= r0; r--) {
|
||||
cell = m_levelColumn->getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
TImageP img = cell.getImage(false);
|
||||
if (!img) return false;
|
||||
bBox = img->getBBox();
|
||||
}
|
||||
|
@ -1484,10 +1559,19 @@ std::wstring TLevelColumnFx::getColumnName() const {
|
|||
|
||||
std::string TLevelColumnFx::getAlias(double frame,
|
||||
const TRenderSettings &info) const {
|
||||
if (!m_levelColumn || m_levelColumn->getCell((int)frame).isEmpty())
|
||||
return std::string();
|
||||
if (!m_levelColumn) return std::string();
|
||||
|
||||
const TXshCell &cell = m_levelColumn->getCell((int)frame);
|
||||
TXshCell cell = m_levelColumn->getCell((int)frame);
|
||||
if (cell.isEmpty() && Preferences::instance()->isImplicitHoldEnabled()) {
|
||||
int r0, r1;
|
||||
m_levelColumn->getRange(r0, r1);
|
||||
for (int r = std::min(r1, (int)frame); r >= r0; r--) {
|
||||
cell = m_levelColumn->getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cell.isEmpty()) return std::string();
|
||||
|
||||
TFilePath fp;
|
||||
TXshSimpleLevel *sl = cell.getSimpleLevel();
|
||||
|
@ -1548,6 +1632,15 @@ TAffine TLevelColumnFx::getDpiAff(int frame) {
|
|||
if (!m_levelColumn) return TAffine();
|
||||
|
||||
TXshCell cell = m_levelColumn->getCell(frame);
|
||||
if (cell.isEmpty() && Preferences::instance()->isImplicitHoldEnabled()) {
|
||||
int r0, r1;
|
||||
m_levelColumn->getRange(r0, r1);
|
||||
for (int r = std::min(r1, frame); r >= r0; r--) {
|
||||
cell = m_levelColumn->getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cell.isEmpty()) return TAffine();
|
||||
|
||||
TXshSimpleLevel *sl = cell.m_level->getSimpleLevel();
|
||||
|
|
|
@ -36,7 +36,7 @@ TXshCellColumn::~TXshCellColumn() { m_cells.clear(); }
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int TXshCellColumn::getRange(int &r0, int &r1) const {
|
||||
int TXshCellColumn::getRange(int &r0, int &r1, bool ignoreLastStop) const {
|
||||
int cellCount = m_cells.size();
|
||||
r0 = m_first;
|
||||
r1 = r0 + cellCount - 1;
|
||||
|
@ -51,8 +51,10 @@ int TXshCellColumn::getRange(int &r0, int &r1) const {
|
|||
r0 = m_first + i;
|
||||
for (i = cellCount - 1; i >= 0 && m_cells[i].isEmpty(); i--) {
|
||||
}
|
||||
|
||||
r1 = m_first + i;
|
||||
if (r1 < m_cells.size() && r1 > r0 && ignoreLastStop &&
|
||||
m_cells[r1].getFrameId().isStopFrame())
|
||||
r1--;
|
||||
return r1 - r0 + 1;
|
||||
}
|
||||
|
||||
|
@ -70,9 +72,9 @@ int TXshCellColumn::getRowCount() const {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int TXshCellColumn::getMaxFrame() const {
|
||||
int TXshCellColumn::getMaxFrame(bool ignoreLastStop) const {
|
||||
int r0, r1;
|
||||
getRange(r0, r1);
|
||||
getRange(r0, r1, ignoreLastStop);
|
||||
return r1;
|
||||
}
|
||||
|
||||
|
|
|
@ -241,7 +241,49 @@ const TXshCell &TXsheet::getCell(const CellPosition &pos) const {
|
|||
if (!column) return emptyCell;
|
||||
TXshCellColumn *xshColumn = column->getCellColumn();
|
||||
if (!xshColumn) return emptyCell;
|
||||
return xshColumn->getCell(pos.frame());
|
||||
int frame = pos.frame();
|
||||
TXshCell cell = xshColumn->getCell(frame);
|
||||
if (cell.isEmpty() && Preferences::instance()->isImplicitHoldEnabled()) {
|
||||
int r0, r1;
|
||||
xshColumn->getRange(r0, r1);
|
||||
for (int r = std::min(r1, pos.frame()); r >= r0; r--) {
|
||||
TXshCell tempCell = xshColumn->getCell(r);
|
||||
if (tempCell.isEmpty()) continue;
|
||||
if (tempCell.getSoundLevel() || tempCell.getSoundTextLevel())
|
||||
return emptyCell;
|
||||
if (tempCell.getFrameId().isStopFrame() && cell.isEmpty())
|
||||
return emptyCell;
|
||||
frame = r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return xshColumn->getCell(frame);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool TXsheet::isImplicitCell(int row, int col) const {
|
||||
return isImplicitCell(CellPosition(row, col));
|
||||
}
|
||||
|
||||
bool TXsheet::isImplicitCell(const CellPosition &pos) const {
|
||||
if (!Preferences::instance()->isImplicitHoldEnabled()) return false;
|
||||
|
||||
TXshColumnP column = m_imp->m_columnSet.getColumn(pos.layer());
|
||||
if (!column) return false;
|
||||
TXshCellColumn *xshColumn = column->getCellColumn();
|
||||
if (!xshColumn) return false;
|
||||
TXshCell tempCell = xshColumn->getCell(pos.frame());
|
||||
if (!tempCell.isEmpty()) return false;
|
||||
|
||||
int r0, r1;
|
||||
xshColumn->getRange(r0, r1);
|
||||
for (int r = std::min(r1, pos.frame()); r >= r0; r--) {
|
||||
tempCell = xshColumn->getCell(r);
|
||||
if (!tempCell.isEmpty()) return true;
|
||||
if (tempCell.getFrameId().isStopFrame()) return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -251,8 +293,7 @@ bool TXsheet::setCell(int row, int col, const TXshCell &cell) {
|
|||
|
||||
bool wasColumnEmpty = isColumnEmpty(col);
|
||||
TXshCellColumn *cellColumn;
|
||||
|
||||
if (!cell.isEmpty()) {
|
||||
if (!cell.isEmpty() && !isImplicitCell(row, col)) {
|
||||
TXshLevel *level = cell.m_level.getPointer();
|
||||
assert(level);
|
||||
|
||||
|
@ -297,7 +338,7 @@ bool TXsheet::setCell(int row, int col, const TXshCell &cell) {
|
|||
if (cell.isEmpty())
|
||||
updateFrameCount();
|
||||
else if (row >= m_imp->m_frameCount)
|
||||
m_imp->m_frameCount = row + 1;
|
||||
m_imp->m_frameCount = row + (cell.getFrameId().isStopFrame() ? 0 : 1);
|
||||
|
||||
TNotifier::instance()->notify(TXsheetChange());
|
||||
|
||||
|
@ -360,7 +401,7 @@ bool TXsheet::setCells(int row, int col, int rowCount, const TXshCell cells[]) {
|
|||
TXshCellColumn *column = touchColumn(col, type)->getCellColumn();
|
||||
if (!column) return false;
|
||||
|
||||
int oldColRowCount = column->getMaxFrame() + 1;
|
||||
int oldColRowCount = column->getMaxFrame(true) + 1;
|
||||
bool ret = column->setCells(row, rowCount, cells);
|
||||
if (!ret || column->isLocked()) {
|
||||
if (wasColumnEmpty) {
|
||||
|
@ -369,7 +410,7 @@ bool TXsheet::setCells(int row, int col, int rowCount, const TXshCell cells[]) {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
int newColRowCount = column->getMaxFrame() + 1;
|
||||
int newColRowCount = column->getMaxFrame(true) + 1;
|
||||
|
||||
TFx *fx = column->getFx();
|
||||
if (wasColumnEmpty && fx && fx->getOutputConnectionCount() == 0)
|
||||
|
@ -396,7 +437,7 @@ void TXsheet::insertCells(int row, int col, int rowCount) {
|
|||
if (!xshColumn) return;
|
||||
xshColumn->insertEmptyCells(row, rowCount);
|
||||
// aggiorno il frame count
|
||||
int fc = xshColumn->getMaxFrame() + 1;
|
||||
int fc = xshColumn->getMaxFrame(true) + 1;
|
||||
if (fc > m_imp->m_frameCount) m_imp->m_frameCount = fc;
|
||||
}
|
||||
|
||||
|
@ -409,7 +450,7 @@ void TXsheet::removeCells(int row, int col, int rowCount) {
|
|||
TXshCellColumn *xshCellColumn = column->getCellColumn();
|
||||
if (!xshCellColumn) return;
|
||||
|
||||
int oldColRowCount = xshCellColumn->getMaxFrame() + 1;
|
||||
int oldColRowCount = xshCellColumn->getMaxFrame(true) + 1;
|
||||
xshCellColumn->removeCells(row, rowCount);
|
||||
|
||||
// aggiornamento framecount
|
||||
|
@ -427,7 +468,7 @@ void TXsheet::clearCells(int row, int col, int rowCount) {
|
|||
TXshCellColumn *xshCellColumn = column->getCellColumn();
|
||||
if (!xshCellColumn) return;
|
||||
|
||||
int oldColRowCount = xshCellColumn->getMaxFrame() + 1;
|
||||
int oldColRowCount = xshCellColumn->getMaxFrame(true) + 1;
|
||||
xshCellColumn->clearCells(row, rowCount);
|
||||
|
||||
// aggiornamento framecount
|
||||
|
@ -636,8 +677,12 @@ void TXsheet::reverseCells(int r0, int c0, int r1, int c1) {
|
|||
for (int j = c0; j <= c1; j++) {
|
||||
int i1, i2;
|
||||
for (i1 = r0, i2 = r1; i1 < i2; i1++, i2--) {
|
||||
TXshCell app1 = getCell(CellPosition(i1, j));
|
||||
TXshCell app2 = getCell(CellPosition(i2, j));
|
||||
TXshCell app1;
|
||||
if (!isImplicitCell(CellPosition(i1, j)))
|
||||
app1 = getCell(CellPosition(i1, j));
|
||||
TXshCell app2;
|
||||
if (!isImplicitCell(CellPosition(i2, j)))
|
||||
app2 = getCell(CellPosition(i2, j));
|
||||
setCell(i1, j, app2);
|
||||
setCell(i2, j, app1);
|
||||
}
|
||||
|
@ -654,7 +699,9 @@ void TXsheet::swingCells(int r0, int c0, int r1, int c1) {
|
|||
|
||||
for (int j = c0; j <= c1; j++) {
|
||||
for (int i1 = r0Mod, i2 = r1 - 1; i2 >= r0; i1++, i2--) {
|
||||
TXshCell cell = getCell(CellPosition(i2, j));
|
||||
TXshCell cell;
|
||||
if (!isImplicitCell(CellPosition(i2, j)))
|
||||
cell = getCell(CellPosition(i2, j));
|
||||
setCell(i1, j, cell);
|
||||
}
|
||||
}
|
||||
|
@ -684,14 +731,17 @@ bool TXsheet::incrementCells(int r0, int c0, int r1, int c1,
|
|||
if (getCell(CellPosition(i + 1, j)).isEmpty()) continue;
|
||||
|
||||
int frame1 = getCell(CellPosition(i, j)).getFrameId().getNumber();
|
||||
if (frame1 == -1) break;
|
||||
if (frame1 == TFrameId::EMPTY_FRAME || frame1 == TFrameId::STOP_FRAME)
|
||||
break;
|
||||
while (!getCell(CellPosition(i + 1, j)).isEmpty() &&
|
||||
!getCell(CellPosition(i + 1, j)).getFrameId().isStopFrame() &&
|
||||
getCell(CellPosition(i + 1, j)).getFrameId().getNumber() ==
|
||||
getCell(CellPosition(i, j)).getFrameId().getNumber())
|
||||
i++, count++;
|
||||
|
||||
int frame2 = getCell(CellPosition(i + 1, j)).getFrameId().getNumber();
|
||||
if (frame2 == -1) break;
|
||||
if (frame2 == TFrameId::EMPTY_FRAME || frame2 == TFrameId::STOP_FRAME)
|
||||
break;
|
||||
|
||||
if (frame1 + count == frame2)
|
||||
continue;
|
||||
|
@ -699,19 +749,26 @@ bool TXsheet::incrementCells(int r0, int c0, int r1, int c1,
|
|||
{
|
||||
int numCells = frame2 - frame1 - count;
|
||||
insertCells(i + 1, j, numCells);
|
||||
TXshCell cell(0, TFrameId::NO_FRAME);
|
||||
forUndo.push_back(std::pair<TRect, TXshCell>(
|
||||
TRect(i + 1, j, i + 1 + numCells - 1, j), TXshCell()));
|
||||
for (int k = 1; k <= numCells; k++)
|
||||
setCell(i + k, j, getCell(CellPosition(i, j)));
|
||||
TRect(i + 1, j, i + 1 + numCells - 1, j), cell));
|
||||
for (int k = 1; k <= numCells; k++) {
|
||||
TXshCell cell;
|
||||
if (!isImplicitCell(CellPosition(i + k, j)))
|
||||
cell = getCell(CellPosition(i, j));
|
||||
setCell(i + k, j, cell);
|
||||
}
|
||||
i += numCells;
|
||||
r1 += numCells;
|
||||
} else // remove
|
||||
{
|
||||
int numCells = count - frame2 + frame1;
|
||||
i = i - numCells;
|
||||
forUndo.push_back(
|
||||
std::pair<TRect, TXshCell>(TRect(i + 1, j, i + 1 + numCells - 1, j),
|
||||
getCell(CellPosition(i + 1, j))));
|
||||
TXshCell cell;
|
||||
if (!isImplicitCell(CellPosition(i + 1, j)))
|
||||
cell = getCell(CellPosition(i + 1, j));
|
||||
forUndo.push_back(std::pair<TRect, TXshCell>(
|
||||
TRect(i + 1, j, i + 1 + numCells - 1, j), cell));
|
||||
removeCells(i + 1, j, numCells);
|
||||
r1 -= numCells;
|
||||
}
|
||||
|
@ -728,8 +785,13 @@ void TXsheet::duplicateCells(int r0, int c0, int r1, int c1, int upTo) {
|
|||
|
||||
for (int j = c0; j <= c1; j++) {
|
||||
insertCells(r1 + 1, j, upTo - (r1 + 1) + 1);
|
||||
for (int i = r1 + 1; i <= upTo; i++)
|
||||
setCell(i, j, getCell(CellPosition(r0 + ((i - (r1 + 1)) % chunk), j)));
|
||||
for (int i = r1 + 1; i <= upTo; i++) {
|
||||
int row = r0 + ((i - (r1 + 1)) % chunk);
|
||||
TXshCell cell;
|
||||
if (!isImplicitCell(CellPosition(row, j)))
|
||||
cell = getCell(CellPosition(row, j));
|
||||
setCell(i, j, cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -746,18 +808,20 @@ void TXsheet::stepCells(int r0, int c0, int r1, int c1, int type) {
|
|||
int k = 0;
|
||||
for (int r = r0; r <= r1; r++)
|
||||
for (int c = c0; c <= c1; c++) {
|
||||
cells[k++] = getCell(CellPosition(r, c));
|
||||
const TXshCell &cell = getCell(CellPosition(r, c));
|
||||
cells[k++] = isImplicitCell(CellPosition(r, c)) ? TXshCell() : cell;
|
||||
}
|
||||
|
||||
int nrows = nr * (type - 1);
|
||||
|
||||
for (int c = c0; c <= c1; ++c) insertCells(r1 + 1, c, nrows);
|
||||
|
||||
bool useImplicitHold = Preferences::instance()->isImplicitHoldEnabled();
|
||||
for (int j = c0; j <= c1; j++) {
|
||||
int i, k;
|
||||
for (i = r0, k = j - c0; k < size; k += nc) {
|
||||
for (int i1 = 0; i1 < type; i1++) {
|
||||
if (cells[k].isEmpty())
|
||||
if (cells[k].isEmpty() || (useImplicitHold && i1 > 0))
|
||||
clearCells(i + i1, j);
|
||||
else
|
||||
setCell(i + i1, j, cells[k]);
|
||||
|
@ -772,13 +836,18 @@ void TXsheet::stepCells(int r0, int c0, int r1, int c1, int type) {
|
|||
void TXsheet::increaseStepCells(int r0, int c0, int &r1, int c1) {
|
||||
int c, size = r1 - r0 + 1;
|
||||
QList<int> ends;
|
||||
bool useImplicit = Preferences::instance()->isImplicitHoldEnabled();
|
||||
for (c = c0; c <= c1; c++) {
|
||||
int r = r0, i = 0, rEnd = r1;
|
||||
while (r <= rEnd) {
|
||||
TXshCell cell = getCell(CellPosition(r, c));
|
||||
if (!cell.isEmpty()) {
|
||||
insertCells(r, c);
|
||||
setCell(r, c, cell);
|
||||
if (useImplicit)
|
||||
insertCells(r + 1, c);
|
||||
else {
|
||||
insertCells(r, c);
|
||||
setCell(r, c, cell);
|
||||
}
|
||||
rEnd++;
|
||||
r++;
|
||||
while (cell == getCell(CellPosition(r, c)) && r <= rEnd) r++;
|
||||
|
@ -848,7 +917,10 @@ void TXsheet::eachCells(int r0, int c0, int r1, int c1, int type) {
|
|||
for (j = r0, i = 0; i < size;
|
||||
j += type) // in cells copio il contenuto delle celle che mi interessano
|
||||
{
|
||||
for (k = c0; k <= c1; k++, i++) cells[i] = getCell(CellPosition(j, k));
|
||||
for (k = c0; k <= c1; k++, i++) {
|
||||
const TXshCell &cell = getCell(CellPosition(j, k));
|
||||
cells[i] = isImplicitCell(j, k) ? TXshCell() : cell;
|
||||
}
|
||||
}
|
||||
|
||||
int c;
|
||||
|
@ -880,19 +952,29 @@ int TXsheet::reframeCells(int r0, int r1, int col, int type, int withBlank) {
|
|||
cells.clear();
|
||||
|
||||
for (int r = r0; r <= r1; r++) {
|
||||
if (cells.size() == 0 || cells.last() != getCell(CellPosition(r, col)))
|
||||
cells.push_back(getCell(CellPosition(r, col)));
|
||||
const TXshCell &cell = getCell(CellPosition(r, col));
|
||||
if (cells.size() == 0 || cells.last() != cell) {
|
||||
if (cell.isEmpty() && cells.last().getFrameId() == TFrameId::STOP_FRAME)
|
||||
continue;
|
||||
cells.push_back(cell);
|
||||
}
|
||||
}
|
||||
|
||||
// if withBlank is greater than -1, remove empty cells from cell order
|
||||
if (withBlank >= 0) {
|
||||
auto itr = cells.begin();
|
||||
while (itr != cells.end()) {
|
||||
if ((*itr).isEmpty())
|
||||
if ((*itr).isEmpty() || (*itr).getFrameId().isStopFrame())
|
||||
itr = cells.erase(itr);
|
||||
else
|
||||
itr++;
|
||||
}
|
||||
|
||||
// Convert implicit cell at end of selected range into a populated cell
|
||||
if (withBlank > 0 && isImplicitCell((r1 + 1), col)) {
|
||||
const TXshCell &origCell = getCell((r1 + 1), col);
|
||||
setCell((r1 + 1), col, origCell);
|
||||
}
|
||||
}
|
||||
|
||||
if (cells.empty()) return 0;
|
||||
|
@ -913,9 +995,13 @@ int TXsheet::reframeCells(int r0, int r1, int col, int type, int withBlank) {
|
|||
removeCells(r0 + nrows, col, nr - nrows);
|
||||
}
|
||||
|
||||
bool useImplicitHold = Preferences::instance()->isImplicitHoldEnabled();
|
||||
for (int i = r0, k = 0; i < r0 + nrows; k++) {
|
||||
TXshLevelP level = cells[k].m_level;
|
||||
if (useImplicitHold && !level) level = getCell(i, col).m_level;
|
||||
for (int i1 = 0; i1 < type; i1++) {
|
||||
if (cells[k].isEmpty())
|
||||
// Cell is empty, find last level
|
||||
if (cells[k].isEmpty() || (useImplicitHold && i1 > 0))
|
||||
clearCells(i + i1, col);
|
||||
else
|
||||
setCell(i + i1, col, cells[k]);
|
||||
|
@ -924,7 +1010,10 @@ int TXsheet::reframeCells(int r0, int r1, int col, int type, int withBlank) {
|
|||
|
||||
if (withBlank > 0) {
|
||||
for (int i1 = 0; i1 < withBlank * type; i1++) {
|
||||
clearCells(i + i1, col);
|
||||
if (useImplicitHold && i1 == 0)
|
||||
setCell(i + i1, col, TXshCell(level, TFrameId::STOP_FRAME));
|
||||
else
|
||||
clearCells(i + i1, col);
|
||||
}
|
||||
i += withBlank * type;
|
||||
}
|
||||
|
@ -1008,6 +1097,7 @@ void TXsheet::rolldownCells(int r0, int c0, int r1, int c1) {
|
|||
If nr>r1-r0+1 add cells, otherwise remove cells. */
|
||||
void TXsheet::timeStretch(int r0, int c0, int r1, int c1, int nr) {
|
||||
int oldNr = r1 - r0 + 1;
|
||||
bool useImplicitHold = Preferences::instance()->isImplicitHoldEnabled();
|
||||
if (nr > oldNr) /* ingrandisce */
|
||||
{
|
||||
int c;
|
||||
|
@ -1019,9 +1109,14 @@ void TXsheet::timeStretch(int r0, int c0, int r1, int c1, int nr) {
|
|||
getCells(r0, c, oldNr, cells.get());
|
||||
insertCells(r0 + 1, c, dn);
|
||||
int i;
|
||||
for (i = nr - 1; i >= 0; i--) {
|
||||
for (i = 0; i < nr; i++) {
|
||||
int j = i * double(oldNr) / double(nr);
|
||||
if (j < i) setCell(i + r0, c, cells[j]);
|
||||
if (j < i) {
|
||||
int prevj = (i - 1) * double(oldNr) / double(nr);
|
||||
TXshCell cell =
|
||||
(useImplicitHold && j == prevj) ? TXshCell() : cells[j];
|
||||
setCell(i + r0, c, cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else /* rimpicciolisce */
|
||||
|
@ -1035,7 +1130,12 @@ void TXsheet::timeStretch(int r0, int c0, int r1, int c1, int nr) {
|
|||
int i;
|
||||
for (i = 0; i < nr; i++) {
|
||||
int j = i * double(oldNr) / double(nr);
|
||||
if (j > i) setCell(i + r0, c, cells[j]);
|
||||
if (j > i) {
|
||||
int prevj = (i - 1) * double(oldNr) / double(nr);
|
||||
TXshCell cell =
|
||||
(useImplicitHold && j == prevj) ? TXshCell() : cells[j];
|
||||
setCell(i + r0, c, cell);
|
||||
}
|
||||
}
|
||||
removeCells(r1 - dn + 1, c, dn);
|
||||
}
|
||||
|
@ -1170,9 +1270,12 @@ void TXsheet::updateFrameCount() {
|
|||
m_imp->m_frameCount = 0;
|
||||
for (int i = 0; i < m_imp->m_columnSet.getColumnCount(); ++i) {
|
||||
TXshColumnP cc = m_imp->m_columnSet.getColumn(i);
|
||||
if (cc && !cc->isEmpty())
|
||||
m_imp->m_frameCount =
|
||||
std::max(m_imp->m_frameCount, cc->getMaxFrame() + 1);
|
||||
if (cc && !cc->isEmpty()) {
|
||||
int maxFrame = cc->getMaxFrame();
|
||||
TXshCell cell = getCell(maxFrame, i);
|
||||
if (cell.getFrameId().isStopFrame()) maxFrame--;
|
||||
m_imp->m_frameCount = std::max(m_imp->m_frameCount, maxFrame + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1744,13 +1847,22 @@ void TXsheet::autoInputCellNumbers(int increment, int interval, int step,
|
|||
int rowUpTo = (r1 == -1) ? rowsCount - 1
|
||||
: ((isOverwrite) ? std::min(r1, r0 + rowsCount - 1)
|
||||
: r0 + rowsCount - 1);
|
||||
bool useImplicitHold = Preferences::instance()->isImplicitHoldEnabled();
|
||||
|
||||
// for each column
|
||||
for (int c = 0; c < columnIndices.size(); c++) {
|
||||
int columnIndex = columnIndices.at(c);
|
||||
TXshLevelP level = levels.at(c);
|
||||
|
||||
// on insertion, insert empty cells first
|
||||
if (!isOverwrite) insertCells(r0, columnIndex, rowsCount);
|
||||
if (!isOverwrite) {
|
||||
// If implicit cell, convert to real cell
|
||||
if (isImplicitCell(r0, columnIndex)) {
|
||||
TXshCell cell = getCell(r0, columnIndex);
|
||||
setCell(r0, columnIndex, cell);
|
||||
}
|
||||
insertCells(r0, columnIndex, rowsCount);
|
||||
}
|
||||
|
||||
// obtain fids to be input
|
||||
std::vector<TFrameId> fids;
|
||||
|
@ -1794,11 +1906,19 @@ void TXsheet::autoInputCellNumbers(int increment, int interval, int step,
|
|||
int step_interv_itr = 0;
|
||||
while (row <= rowUpTo) {
|
||||
// input cell
|
||||
if (step_interv_itr < step)
|
||||
setCell(row, columnIndex, TXshCell(level, fids.at(fid_itr)));
|
||||
if (step_interv_itr < step) {
|
||||
TXshCell cell;
|
||||
if (useImplicitHold && step_interv_itr == 0)
|
||||
cell = TXshCell(level, fids.at(fid_itr));
|
||||
setCell(row, columnIndex, cell);
|
||||
}
|
||||
// .. or set empty cell as interval
|
||||
else
|
||||
setCell(row, columnIndex, TXshCell());
|
||||
else {
|
||||
TXshCell emptyCell;
|
||||
if (useImplicitHold && step_interv_itr == step)
|
||||
emptyCell = TXshCell(level, TFrameId::STOP_FRAME);
|
||||
setCell(row, columnIndex, emptyCell);
|
||||
}
|
||||
|
||||
// increment
|
||||
step_interv_itr++;
|
||||
|
|
|
@ -17,6 +17,8 @@ TFrameId qstringToFrameId(QString str) {
|
|||
return TFrameId::EMPTY_FRAME;
|
||||
else if (str == "-" || str == "-2")
|
||||
return TFrameId::NO_FRAME;
|
||||
else if (str == "x" || str == "-3")
|
||||
return TFrameId::STOP_FRAME;
|
||||
|
||||
QString regExpStr = QString("^%1$").arg(TFilePath::fidRegExpStr());
|
||||
QRegExp rx(regExpStr);
|
||||
|
|
|
@ -287,7 +287,7 @@ void TXshSoundColumn::saveData(TOStream &os) {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int TXshSoundColumn::getRange(int &r0, int &r1) const {
|
||||
int TXshSoundColumn::getRange(int &r0, int &r1, bool ignoreLastStop) const {
|
||||
r0 = getFirstRow();
|
||||
r1 = getMaxFrame();
|
||||
return r1 - r0 + 1;
|
||||
|
@ -301,7 +301,7 @@ int TXshSoundColumn::getRowCount() const {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int TXshSoundColumn::getMaxFrame() const {
|
||||
int TXshSoundColumn::getMaxFrame(bool ignoreLastStop) const {
|
||||
int levelsCount = m_levels.size();
|
||||
if (levelsCount == 0) return -1;
|
||||
return m_levels.at(levelsCount - 1)->getVisibleEndFrame();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "toonz/txsheet.h"
|
||||
#include "toonz/fxdag.h"
|
||||
#include "toonz/txshzeraryfxlevel.h"
|
||||
#include "toonz/preferences.h"
|
||||
|
||||
#include "tstream.h"
|
||||
|
||||
|
@ -21,6 +22,7 @@ TXshZeraryFxColumn::TXshZeraryFxColumn(int frameCount)
|
|||
m_zeraryColumnFx->setColumn(this);
|
||||
m_zeraryFxLevel->addRef();
|
||||
m_zeraryFxLevel->setColumn(this);
|
||||
if (frameCount <= 0) return;
|
||||
for (int i = 0; i < frameCount; i++)
|
||||
setCell(i, TXshCell(m_zeraryFxLevel, TFrameId(1)));
|
||||
}
|
||||
|
@ -37,8 +39,13 @@ TXshZeraryFxColumn::TXshZeraryFxColumn(const TXshZeraryFxColumn &src)
|
|||
m_zeraryFxLevel->setColumn(this);
|
||||
m_first = src.m_first;
|
||||
int i;
|
||||
for (i = 0; i < (int)src.m_cells.size(); i++)
|
||||
m_cells.push_back(TXshCell(m_zeraryFxLevel, src.m_cells[i].getFrameId()));
|
||||
for (i = 0; i < (int)src.m_cells.size(); i++) {
|
||||
if (Preferences::instance()->isImplicitHoldEnabled() &&
|
||||
src.m_cells[i].getFrameId().isEmptyFrame())
|
||||
m_cells.push_back(TXshCell(0, src.m_cells[i].getFrameId()));
|
||||
else
|
||||
m_cells.push_back(TXshCell(m_zeraryFxLevel, src.m_cells[i].getFrameId()));
|
||||
}
|
||||
assert((int)src.m_cells.size() == (int)m_cells.size());
|
||||
TFx *fx = src.getZeraryColumnFx()->getZeraryFx();
|
||||
if (fx) {
|
||||
|
@ -104,9 +111,13 @@ bool TXshZeraryFxColumn::setCells(int row, int rowCount,
|
|||
bool isEmptyColumn = isEmpty() && getZeraryColumnFx()->getZeraryFx() == 0;
|
||||
int i;
|
||||
for (i = 0; i < rowCount; i++) {
|
||||
if (isEmptyColumn)
|
||||
newCells.push_back(TXshCell(m_zeraryFxLevel, cells[i].getFrameId()));
|
||||
else
|
||||
if (isEmptyColumn) {
|
||||
if (Preferences::instance()->isImplicitHoldEnabled() &&
|
||||
cells[i].getFrameId().isEmptyFrame())
|
||||
newCells.push_back(TXshCell(0, cells[i].getFrameId()));
|
||||
else
|
||||
newCells.push_back(TXshCell(m_zeraryFxLevel, cells[i].getFrameId()));
|
||||
} else
|
||||
newCells.push_back(cells[i]);
|
||||
}
|
||||
// Sto settando delle celle in una colonna nuova, devo settare anche
|
||||
|
@ -141,7 +152,7 @@ void TXshZeraryFxColumn::loadData(TIStream &is) {
|
|||
|
||||
int r0, r1;
|
||||
bool touched = false;
|
||||
const TXshCell cell(m_zeraryFxLevel, TFrameId(1));
|
||||
TXshCell cell(m_zeraryFxLevel, TFrameId(1));
|
||||
std::string tagName;
|
||||
while (is.matchTag(tagName)) {
|
||||
if (tagName == "status") {
|
||||
|
@ -157,6 +168,10 @@ void TXshZeraryFxColumn::loadData(TIStream &is) {
|
|||
}
|
||||
int r, n;
|
||||
is >> r >> n;
|
||||
if (is.getTagAttribute("stopframe") == "yes")
|
||||
cell.m_frameId = TFrameId::STOP_FRAME;
|
||||
else
|
||||
cell.m_frameId = 1;
|
||||
for (int i = 0; i < n; i++) setCell(r++, cell);
|
||||
} else
|
||||
throw TException("expected <cell>");
|
||||
|
@ -181,9 +196,35 @@ void TXshZeraryFxColumn::saveData(TOStream &os) {
|
|||
for (int r = r0; r <= r1; r++) {
|
||||
TXshCell cell = getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
int n = 1;
|
||||
while (r + n <= r1 && !getCell(r + n).isEmpty()) n++;
|
||||
os.child("cell") << r << n;
|
||||
int fnum = cell.m_frameId.getNumber();
|
||||
if (fnum > 1) fnum = 1; // Should always be 1 unless it's stopframe
|
||||
int n = 1;
|
||||
|
||||
if (r < r1) {
|
||||
TXshCell cell2 = getCell(r + 1);
|
||||
if (!cell2.isEmpty()) {
|
||||
int fnum2 = cell2.m_frameId.getNumber();
|
||||
if (fnum2 > 1) fnum2 = 1; // Should always be 1 unless it's stopframe
|
||||
if (fnum == fnum2) {
|
||||
n++;
|
||||
for (;;) {
|
||||
if (r + n > r1) break;
|
||||
cell2 = getCell(r + n);
|
||||
if (cell2.isEmpty()) break;
|
||||
fnum2 = cell2.m_frameId.getNumber();
|
||||
if (fnum2 > 1)
|
||||
fnum2 = 1; // Should always be 1 unless it's stopframe
|
||||
if (fnum != fnum2) break;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
std::map<std::string, std::string> attr;
|
||||
if (cell.m_frameId.isStopFrame()) attr["stopframe"] = "yes";
|
||||
os.openChild("cell", attr);
|
||||
os << r << n;
|
||||
os.closeChild();
|
||||
r += n - 1;
|
||||
}
|
||||
os.closeChild();
|
||||
|
|
Loading…
Reference in a new issue