#include "toonz/tcolumnfxset.h" // TnzLib includes #include "toonz/tcolumnfx.h" // TnzBase includes #include "tfx.h" // TnzCore includes #include "tstream.h" #include "texception.h" TFxSet::TFxSet() //: m_xsheetFx(0) { } TFxSet::~TFxSet() { // delete m_xsheetFx; clear(); } void TFxSet::addFx(TFx *fx) { std::set::iterator it = m_fxs.find(fx); if (it == m_fxs.end()) { fx->addRef(); m_fxs.insert(fx); fx->setNewIdentifier(); } } void TFxSet::getFxs(std::set &fxs) { fxs.insert(m_fxs.begin(), m_fxs.end()); } void TFxSet::saveData(TOStream &os, int occupiedColumnCount) { std::set::iterator it; for (it = m_fxs.begin(); it != m_fxs.end(); ++it) { TRasterFx *rasterFx = dynamic_cast(*it); if (rasterFx) { TColumnFx *columnFx = dynamic_cast(rasterFx); if (columnFx && (columnFx->getColumnIndex() == -1 || columnFx->getColumnIndex() >= occupiedColumnCount)) continue; } os.openChild("fxnode"); os << (*it); os.closeChild(); } } int TFxSet::getFxCount() const { return m_fxs.size(); } bool TFxSet::removeFx(TFx *fx) { std::set::iterator it = m_fxs.find(fx); if (it != m_fxs.end()) { TFx *fx = *it; fx->release(); m_fxs.erase(fx); return true; } else return false; } TFx *TFxSet::getFx(int index) const { assert(0 <= index && index < getFxCount()); std::set::const_iterator it = m_fxs.begin(); std::advance(it, index); return *it; } TFx *TFxSet::getFx(const std::string &id) const { std::set::const_iterator it; for (it = m_fxs.begin(); it != m_fxs.end(); ++it) { // TFx *fx = *it; //if (fx->getId() == id) // return fx; } return 0; } void TFxSet::clear() { std::set::iterator it; for (it = m_fxs.begin(); it != m_fxs.end(); ++it) { TFx *fx = *it; fx->release(); } m_fxs.clear(); } void TFxSet::loadData(TIStream &is) { clear(); string tagName; while (is.openChild(tagName)) { if (tagName == "fxnode") { TPersist *p = 0; is >> p; // NOTE: In current implementation p is sharedly owned by is - it's automatically // released upon stream destruction if the below assignment fails if (TFx *fx = dynamic_cast(p)) { addFx(fx); } } else { throw TException("TFxSet, unknown tag: " + tagName); } is.closeChild(); } } TFx *getActualFx(TFx *fx) { // Zerary fxs and zerary COLUMN fxs are separate, and fx port connections // are stored in the actual zerary fx. // It's sad - couldn't we do something about it? TZeraryColumnFx *zeraryColumnFx = dynamic_cast(fx); return zeraryColumnFx ? zeraryColumnFx->getZeraryFx() : fx; } TFx *searchFx(const std::map &table, TFx *fx) { std::map::const_iterator it = table.find(fx); return it == table.end() ? 0 : it->second; } void updateFxLinks(const std::map &table) { // The input table is made of (original, cloned) couples. // The purpose of this function is that of replicating the hierarchycal // structure from the first fxs to the seconds. std::map::const_iterator it; for (it = table.begin(); it != table.end(); ++it) { TFx *fx = getActualFx(it->first), *fx2 = getActualFx(it->second); if (!fx || !fx2) continue; for (int i = 0; i < fx->getInputPortCount(); ++i) { TFx *inputFx = fx->getInputPort(i)->getFx(); TFx *inputFx2 = 0; if (inputFx) { inputFx2 = searchFx(table, inputFx); inputFx = getActualFx(inputFx); // Normally, the above should be enough. However, it seems that // the possibility of the input table being 'incomplete' must be dealt with // (why is it not asserted >_< !) while (inputFx && !inputFx2 && (inputFx->getInputPortCount() > 0)) { // So, well... this block tries to delve deeper in the hierarchy // until a suitable mapped children is found... Yeah, sure... TFxPort *port = inputFx->getInputPort(0); inputFx = port->getFx(); inputFx2 = searchFx(table, inputFx); inputFx = getActualFx(inputFx); } } if (inputFx2) fx2->getInputPort(i)->setFx(inputFx2); } } }