Bring in OpenToonz updates as of 10/20 (#400)

* fix saving fx ports

Signed-off-by: Jeremy Bullock <jcbullock@gmail.com>

* fix palette gizmo target

Signed-off-by: Jeremy Bullock <jcbullock@gmail.com>

* export subxsheet column to xdts

Signed-off-by: Jeremy Bullock <jcbullock@gmail.com>

* fix particles fx with sub xsheet control

Signed-off-by: Jeremy Bullock <jcbullock@gmail.com>

* fix crash on reverting scene

Signed-off-by: Jeremy Bullock <jcbullock@gmail.com>

* Fix crash on closing Tahoma with a floating level strip.

Co-authored-by: shun-iwasawa <shun.iwasawa@ghibli.jp>
This commit is contained in:
Jeremy Bullock 2020-10-21 15:00:03 -06:00 committed by GitHub
parent fe1084fcc0
commit 6954f4d14c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 87 additions and 61 deletions

View file

@ -873,11 +873,10 @@ void TFx::saveData(TOStream &os) {
} }
os.openChild("ports"); os.openChild("ports");
for (PortTable::iterator pit = m_imp->m_portTable.begin(); for (auto &namePort : m_imp->m_portArray) {
pit != m_imp->m_portTable.end(); ++pit) { os.openChild(namePort.first);
os.openChild(pit->first); if (namePort.second->isConnected())
if (pit->second->isConnected()) os << TFxP(namePort.second->getFx()).getPointer();
os << TFxP(pit->second->getFx()).getPointer();
os.closeChild(); os.closeChild();
} }
os.closeChild(); os.closeChild();

View file

@ -486,7 +486,11 @@ void FilmstripFrames::hideEvent(QHideEvent *) {
// active viewer change // active viewer change
disconnect(app, SIGNAL(activeViewerChanged()), this, SLOT(getViewer())); disconnect(app, SIGNAL(activeViewerChanged()), this, SLOT(getViewer()));
if (m_viewer) { // if the level strip is floating during shutting down Tahoma2D
// it can cause a crash disconnecting from the viewer which was already
// destroyed. Checking the fps is a janky way to ensure the viewer is
// stil relevant.
if (m_viewer && m_viewer->getFPS() > -100) {
disconnect(m_viewer, SIGNAL(onZoomChanged()), this, SLOT(update())); disconnect(m_viewer, SIGNAL(onZoomChanged()), this, SLOT(update()));
disconnect(m_viewer, SIGNAL(refreshNavi()), this, SLOT(update())); disconnect(m_viewer, SIGNAL(refreshNavi()), this, SLOT(update()));
m_viewer = nullptr; m_viewer = nullptr;
@ -602,8 +606,7 @@ void FilmstripFrames::paintEvent(QPaintEvent *evt) {
QRectF naviRatio( QRectF naviRatio(
(-(float)m_viewer->width() * 0.5f - (float)imgBottomLeft.x) / (-(float)m_viewer->width() * 0.5f - (float)imgBottomLeft.x) /
imgSizeInViewer.width(), imgSizeInViewer.width(),
1.0f - 1.0f - ((float)m_viewer->height() * 0.5f - (float)imgBottomLeft.y) /
((float)m_viewer->height() * 0.5f - (float)imgBottomLeft.y) /
imgSizeInViewer.height(), imgSizeInViewer.height(),
(float)m_viewer->width() / imgSizeInViewer.width(), (float)m_viewer->width() / imgSizeInViewer.width(),
(float)m_viewer->height() / imgSizeInViewer.height()); (float)m_viewer->height() / imgSizeInViewer.height());
@ -1598,6 +1601,7 @@ void Filmstrip::onChooseLevelComboChanged(int index) {
void Filmstrip::updateChooseLevelComboItems() { void Filmstrip::updateChooseLevelComboItems() {
// clear items // clear items
m_chooseLevelCombo->clear(); m_chooseLevelCombo->clear();
for (auto oldLevel : m_levels) oldLevel->release();
m_levels.clear(); m_levels.clear();
std::map<TXshSimpleLevel *, TFrameId> new_workingFrames; std::map<TXshSimpleLevel *, TFrameId> new_workingFrames;
@ -1616,6 +1620,7 @@ void Filmstrip::updateChooseLevelComboItems() {
// register only used level in xsheet // register only used level in xsheet
if (!scene->getTopXsheet()->isLevelUsed(sl)) continue; if (!scene->getTopXsheet()->isLevelUsed(sl)) continue;
sl->addRef();
m_levels.push_back(sl); m_levels.push_back(sl);
// create new m_workingFrames map with the new levelset // create new m_workingFrames map with the new levelset
@ -1689,7 +1694,10 @@ void Filmstrip::updateCurrentLevelComboItem() {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
Filmstrip::~Filmstrip() {} Filmstrip::~Filmstrip() {
for (auto level : m_levels) level->release();
m_levels.clear();
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View file

@ -600,7 +600,7 @@ void FilmstripFrameHeadGadget::drawShiftTraceMarker(QPainter &p) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool FilmstripFrameHeadGadget::eventFilter(QObject *obj, QEvent *e) { bool FilmstripFrameHeadGadget::eventFilter(QObject *obj, QEvent *e) {
if (e->type() == QEvent::Close || e->type() == QEvent::Hide) return false; if (e->type() != QEvent::MouseButtonPress && e->type() != QEvent::MouseButtonDblClick && e->type() != QEvent::MouseMove) return false;
// shift & trace case // shift & trace case
if (CommandManager::instance()->getAction(MI_ShiftTrace)->isChecked()) if (CommandManager::instance()->getAction(MI_ShiftTrace)->isChecked())

View file

@ -377,11 +377,11 @@ void modifyColor(const T &modifier) {
TUndo *undo; TUndo *undo;
TStyleSelection *selection = dynamic_cast<TStyleSelection *>( TStyleSelection *selection = dynamic_cast<TStyleSelection *>(
TApp::instance()->getCurrentSelection()->getSelection()); TApp::instance()->getCurrentSelection()->getSelection());
if (selection) { if (selection && !selection->isEmpty()) {
undo = new GizmoUndo(*selection); undo = new GizmoUndo(*selection);
getStyleIds(styleIds, *selection); getStyleIds(styleIds, *selection);
} }
/*-- StyleSelectionが有効でない場合はカレントStyleを用いる --*/ // modify the current style if the style selection is not active or is empty
else { else {
TStyleSelection tmpSelection; TStyleSelection tmpSelection;
tmpSelection.setPaletteHandle(paletteHandle); tmpSelection.setPaletteHandle(paletteHandle);

View file

@ -7,6 +7,7 @@
#include "toonz/txsheet.h" #include "toonz/txsheet.h"
#include "toonz/txshcell.h" #include "toonz/txshcell.h"
#include "toonz/txshsimplelevel.h" #include "toonz/txshsimplelevel.h"
#include "toonz/txshchildlevel.h"
#include "toonz/txsheethandle.h" #include "toonz/txsheethandle.h"
#include "toonz/tscenehandle.h" #include "toonz/tscenehandle.h"
#include "toonz/preferences.h" #include "toonz/preferences.h"
@ -201,15 +202,17 @@ QVector<TFrameId> XdtsFieldTrackItem::getCellFrameIdTrack() const {
QString XdtsFieldTrackItem::build(TXshCellColumn *column) { QString XdtsFieldTrackItem::build(TXshCellColumn *column) {
// register the firstly-found level // register the firstly-found level
TXshSimpleLevel *level = nullptr; TXshLevel *level = nullptr;
TXshCell prevCell; TXshCell prevCell;
int r0, r1; int r0, r1;
column->getRange(r0, r1); column->getRange(r0, r1);
if (r0 > 0) addFrame(0, TFrameId(-1)); if (r0 > 0) addFrame(0, TFrameId(-1));
for (int row = r0; row <= r1; row++) { for (int row = r0; row <= r1; row++) {
TXshCell cell = column->getCell(row); TXshCell cell = column->getCell(row);
// try to register the level // try to register the level. simple levels and sub xsheet levels are
if (!level && cell.getSimpleLevel()) level = cell.getSimpleLevel(); // exported
if (!level) level = cell.getSimpleLevel();
if (!level) level = cell.getChildLevel();
// if the level does not match with the registered one, // if the level does not match with the registered one,
// handle as the empty cell // handle as the empty cell
if (!level || cell.m_level != level) cell = TXshCell(); if (!level || cell.m_level != level) cell = TXshCell();

View file

@ -68,9 +68,11 @@ private:
int m_frame; //!< Frame this fx redirects to int m_frame; //!< Frame this fx redirects to
TFxTimeRegion m_timeRegion; //!< Input (outer) valid column frame range TFxTimeRegion m_timeRegion; //!< Input (outer) valid column frame range
TRasterFxPort m_port; //!< Input port TRasterFxPort m_port; //!< Input port
TXshCellColumn *m_cellColumn;
public: public:
TimeShuffleFx() : TRasterFx(), m_frame(0), m_timeRegion() { TimeShuffleFx()
: TRasterFx(), m_frame(0), m_timeRegion(), m_cellColumn(nullptr) {
addInputPort("source", m_port); addInputPort("source", m_port);
} }
~TimeShuffleFx() {} ~TimeShuffleFx() {}
@ -81,6 +83,7 @@ public:
fx->setFrame(m_frame); fx->setFrame(m_frame);
fx->setTimeRegion(getTimeRegion()); fx->setTimeRegion(getTimeRegion());
fx->setCellColumn(m_cellColumn);
return fx; return fx;
} }
@ -93,12 +96,21 @@ public:
} }
TFxTimeRegion getTimeRegion() const override { return m_timeRegion; } TFxTimeRegion getTimeRegion() const override { return m_timeRegion; }
void setCellColumn(TXshCellColumn *cellColumn) { m_cellColumn = cellColumn; }
bool canHandle(const TRenderSettings &info, double frame) override { bool canHandle(const TRenderSettings &info, double frame) override {
return true; return true;
} }
std::string getPluginId() const override { return std::string(); } std::string getPluginId() const override { return std::string(); }
int getLevelFrame(int frame) const {
if (!m_cellColumn) return m_frame;
TXshCell cell = m_cellColumn->getCell(tfloor(frame));
assert(!cell.isEmpty());
return cell.m_frameId.getNumber() - 1;
}
void doCompute(TTile &tile, double frame, void doCompute(TTile &tile, double frame,
const TRenderSettings &ri) override { const TRenderSettings &ri) override {
if (!m_port.isConnected()) { if (!m_port.isConnected()) {
@ -107,25 +119,25 @@ public:
} }
// Exchange frame with the stored one // Exchange frame with the stored one
TRasterFxP(m_port.getFx())->compute(tile, m_frame, ri); TRasterFxP(m_port.getFx())->compute(tile, getLevelFrame(frame), ri);
} }
bool doGetBBox(double frame, TRectD &bbox, bool doGetBBox(double frame, TRectD &bbox,
const TRenderSettings &info) override { const TRenderSettings &info) override {
if (!m_port.isConnected()) return false; if (!m_port.isConnected()) return false;
return TRasterFxP(m_port.getFx())
return TRasterFxP(m_port.getFx())->doGetBBox(m_frame, bbox, info); ->doGetBBox(getLevelFrame(frame), bbox, info);
} }
std::string getAlias(double frame, std::string getAlias(double frame,
const TRenderSettings &info) const override { const TRenderSettings &info) const override {
return TRasterFx::getAlias(m_frame, info); return TRasterFx::getAlias(getLevelFrame(frame), info);
} }
void doDryCompute(TRectD &rect, double frame, void doDryCompute(TRectD &rect, double frame,
const TRenderSettings &info) override { const TRenderSettings &info) override {
if (m_port.isConnected()) if (m_port.isConnected())
TRasterFxP(m_port.getFx())->dryCompute(rect, m_frame, info); TRasterFxP(m_port.getFx())->dryCompute(rect, getLevelFrame(frame), info);
} }
private: private:
@ -261,8 +273,9 @@ public:
} }
TFxP makeFx() { TFxP makeFx() {
return (!m_fx) ? TFxP() : (m_aff == TAffine()) ? m_fx : TFxUtil::makeAffine( return (!m_fx)
m_fx, m_aff); ? TFxP()
: (m_aff == TAffine()) ? m_fx : TFxUtil::makeAffine(m_fx, m_aff);
} }
}; };
@ -272,11 +285,13 @@ public:
namespace { namespace {
TFxP timeShuffle(TFxP fx, int frame, TFxTimeRegion timeRegion) { TFxP timeShuffle(TFxP fx, int frame, TFxTimeRegion timeRegion,
TXshCellColumn *cellColumn) {
TimeShuffleFx *timeShuffle = new TimeShuffleFx(); TimeShuffleFx *timeShuffle = new TimeShuffleFx();
timeShuffle->setFrame(frame); timeShuffle->setFrame(frame);
timeShuffle->setTimeRegion(timeRegion); timeShuffle->setTimeRegion(timeRegion);
timeShuffle->setCellColumn(cellColumn);
if (!timeShuffle->connect("source", fx.getPointer())) if (!timeShuffle->connect("source", fx.getPointer()))
assert(!"Could not connect ports!"); assert(!"Could not connect ports!");
@ -511,7 +526,7 @@ QString getNoteText(TXsheet *xsh, double row, int col, int noteColumnIndex,
return cell.getSoundTextLevel()->getFrameText(cell.m_frameId.getNumber() - 1); return cell.getSoundTextLevel()->getFrameText(cell.m_frameId.getNumber() - 1);
} }
}; }; // namespace
//*************************************************************************************************** //***************************************************************************************************
// FxBuilder definition // FxBuilder definition
@ -812,7 +827,8 @@ PlacedFx FxBuilder::makePF(TLevelColumnFx *lcfx) {
FxBuilder builder(m_scene, xsh, levelFrame, m_whichLevels, m_isPreview); FxBuilder builder(m_scene, xsh, levelFrame, m_whichLevels, m_isPreview);
// Then, add the TimeShuffleFx // Then, add the TimeShuffleFx
pf.m_fx = timeShuffle(builder.buildFx(), levelFrame, lcfx->getTimeRegion()); pf.m_fx = timeShuffle(builder.buildFx(), levelFrame, lcfx->getTimeRegion(),
lcfx->getColumn());
pf.m_fx->setIdentifier(lcfx->getIdentifier()); pf.m_fx->setIdentifier(lcfx->getIdentifier());
pf.m_fx->getAttributes()->passiveCacheDataIdx() = pf.m_fx->getAttributes()->passiveCacheDataIdx() =
lcfx->getAttributes()->passiveCacheDataIdx(); lcfx->getAttributes()->passiveCacheDataIdx();
@ -925,10 +941,10 @@ PlacedFx FxBuilder::makePF(TZeraryColumnFx *zcfx) {
// Build // Build
PlacedFx pf; PlacedFx pf;
pf.m_columnIndex = zcfx->getColumn()->getIndex(); pf.m_columnIndex = zcfx->getColumn()->getIndex();
pf.m_fx = fx->clone( pf.m_fx =
false); // Detach the fx with a clone. Why? It's typically done to fx->clone(false); // Detach the fx with a clone. Why? It's typically done
// build fx connections in the render-tree freely. Here, it's // to build fx connections in the render-tree freely.
// used just for particles, I guess... // Here, it's used just for particles, I guess...
// Deal with input sub-trees // Deal with input sub-trees
for (int i = 0; i < fx->getInputPortCount(); ++i) { for (int i = 0; i < fx->getInputPortCount(); ++i) {
// Note that only particles should end up here, currently // Note that only particles should end up here, currently