#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<TFx *>::iterator it = m_fxs.find(fx);
if (it == m_fxs.end()) {
fx->addRef();
m_fxs.insert(fx);
fx->setNewIdentifier();
}
}
void TFxSet::getFxs(std::set<TFx *> &fxs)
{
fxs.insert(m_fxs.begin(), m_fxs.end());
}
void TFxSet::saveData(TOStream &os, int occupiedColumnCount)
{
std::set<TFx *>::iterator it;
for (it = m_fxs.begin(); it != m_fxs.end(); ++it) {
TRasterFx *rasterFx = dynamic_cast<TRasterFx *>(*it);
if (rasterFx) {
TColumnFx *columnFx = dynamic_cast<TColumnFx *>(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<TFx *>::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<TFx *>::const_iterator it = m_fxs.begin();
std::advance(it, index);
return *it;
}
TFx *TFxSet::getFx(const std::string &id) const
{
std::set<TFx *>::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<TFx *>::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<TFx *>(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<TZeraryColumnFx *>(fx);
return zeraryColumnFx ? zeraryColumnFx->getZeraryFx() : fx;
}
TFx *searchFx(const std::map<TFx *, TFx *> &table, TFx *fx)
{
std::map<TFx *, TFx *>::const_iterator it = table.find(fx);
return it == table.end() ? 0 : it->second;
}
void updateFxLinks(const std::map<TFx *, TFx *> &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<TFx *, TFx *>::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);
}
}
}