| |
| |
|
|
| #include "tsystem.h" |
| #include "tstream.h" |
| #include "tfilepath_io.h" |
| #include "tfunctorinvoker.h" |
| |
| |
| #include "tunit.h" |
| #include "tparamcontainer.h" |
| #include "tparamset.h" |
| #include "tmacrofx.h" |
| #include "tparamchange.h" |
| |
| |
| #include "ext/plasticskeleton.h" |
| |
| |
| #include "toonz/tstageobjecttree.h" |
| #include "toonz/txsheet.h" |
| #include "toonz/txsheethandle.h" |
| #include "toonz/fxdag.h" |
| #include "toonz/txshzeraryfxcolumn.h" |
| #include "toonz/tcolumnfx.h" |
| #include "toonz/tfxhandle.h" |
| #include "toonz/tobjecthandle.h" |
| |
| |
| #include "toonzqt/functionviewer.h" |
| #include "toonzqt/dvdialog.h" |
| #include "toonzqt/gutil.h" |
| #include "toonzqt/plasticvertexselection.h" |
| #include "tw/stringtable.h" |
| |
| |
| #include <QMenu> |
| #include <QAction> |
| #include <QFileDialog> |
| #include <QMouseEvent> |
| #include <QMetaObject> |
| #include <QColor> |
| #include <QApplication> // for drag&drop |
| #include <QDrag> |
| #include <QMimeData> |
| |
| #include "toonzqt/functiontreeviewer.h" |
| |
| |
| |
| |
| |
| namespace |
| { |
| |
| class ParamChannelGroup : public FunctionTreeModel::ParamWrapper, public FunctionTreeModel::ChannelGroup |
| { |
| public: |
| ParamChannelGroup(TParam *param, const wstring &fxId, string ¶mName); |
| |
| void refresh(); |
| void *getInternalPointer() const; |
| }; |
| |
| |
| |
| class StageObjectChannelGroup : public FunctionTreeModel::ChannelGroup |
| { |
| public: |
| TStageObject *m_stageObject; |
| FunctionTreeModel::ChannelGroup *m_plasticGroup; |
| |
| public: |
| StageObjectChannelGroup(TStageObject *pegbar); |
| ~StageObjectChannelGroup(); |
| |
| QString getShortName() const; |
| QString getLongName() const; |
| |
| QString getIdName() const; |
| |
| void *getInternalPointer() const { return static_cast<void *>(m_stageObject); } |
| |
| TStageObject *getStageObject() const { return m_stageObject; } |
| QVariant data(int role) const; |
| }; |
| |
| |
| |
| class SkVDChannelGroup : public FunctionTreeModel::ChannelGroup |
| { |
| public: |
| StageObjectChannelGroup *m_stageObjectGroup; |
| const QString *m_vxName; |
| |
| public: |
| SkVDChannelGroup(const QString *vxName, StageObjectChannelGroup *stageGroup) |
| : ChannelGroup(*vxName), m_stageObjectGroup(stageGroup), m_vxName(vxName) {} |
| |
| QString getShortName() const { return m_stageObjectGroup->getShortName(); } |
| QString getLongName() const { return *m_vxName; } |
| |
| void *getInternalPointer() const { return (void *)m_vxName; } |
| |
| static inline bool compareStr(const TreeModel::Item *item, const QString &str) |
| { |
| const QString &thisStr = static_cast<const SkVDChannelGroup *>(item)->getLongName(); |
| return (QString::localeAwareCompare(thisStr, str) < 0); |
| } |
| |
| QVariant data(int role) const; |
| }; |
| |
| } |
| |
| |
| |
| |
| |
| |
| |
| FunctionTreeModel::ChannelGroup::ChannelGroup(const QString &name) |
| : m_name(name), m_showFilter(ShowAllChannels) |
| { |
| } |
| |
| |
| |
| FunctionTreeModel::ChannelGroup::~ChannelGroup() |
| { |
| } |
| |
| |
| |
| bool FunctionTreeModel::ChannelGroup::isActive() const |
| { |
| |
| int c, childCount = getChildCount(); |
| for (c = 0; c != childCount; ++c) |
| if (static_cast<Item *>(getChild(c))->isActive()) |
| return true; |
| |
| return false; |
| } |
| |
| |
| |
| bool FunctionTreeModel::ChannelGroup::isAnimated() const |
| { |
| |
| int c, childCount = getChildCount(); |
| for (c = 0; c != childCount; ++c) |
| if (static_cast<Item *>(getChild(c))->isAnimated()) |
| return true; |
| |
| return false; |
| } |
| |
| |
| |
| QVariant FunctionTreeModel::ChannelGroup::data(int role) const |
| { |
| if (role == Qt::DisplayRole) |
| return getLongName(); |
| else if (role == Qt::DecorationRole) { |
| bool animated = isAnimated(); |
| bool active = isActive(); |
| |
| if (active) { |
| static QIcon folderAnimOpen(":Resources/folderanim_open.png"); |
| static QIcon folderAnimClose(":Resources/folderanim_close.png"); |
| static QIcon folderOpen(":Resources/folder_open.png"); |
| static QIcon folderClose(":Resources/folder_close.png"); |
| |
| return animated ? isOpen() ? folderAnimOpen : folderAnimClose : isOpen() ? folderOpen : folderClose; |
| } else { |
| static QIcon folderAnimOpen(":Resources/folderanim_open_off.png"); |
| static QIcon folderAnimClose(":Resources/folderanim_close_off.png"); |
| static QIcon folderOpen(":Resources/folder_open_off.png"); |
| static QIcon folderClose(":Resources/folder_close_off.png"); |
| |
| return animated ? isOpen() ? folderAnimOpen : folderAnimClose : isOpen() ? folderOpen : folderClose; |
| } |
| } else |
| return Item::data(role); |
| } |
| |
| |
| |
| |
| void FunctionTreeModel::ChannelGroup::applyShowFilter() |
| { |
| int i, itemCount = getChildCount(); |
| for (i = 0; i < itemCount; i++) { |
| FunctionTreeModel::Channel *channel = dynamic_cast<FunctionTreeModel::Channel *>(getChild(i)); |
| |
| if (!channel) { |
| FunctionTreeModel::ChannelGroup *channelGroup = |
| dynamic_cast<FunctionTreeModel::ChannelGroup *>(getChild(i)); |
| if (!channelGroup) |
| continue; |
| |
| channelGroup->setShowFilter(m_showFilter); |
| continue; |
| } |
| |
| bool showItem = |
| (m_showFilter == ShowAllChannels) || channel->getParam()->hasKeyframes(); |
| |
| QModelIndex modelIndex = createIndex(); |
| getModel()->setRowHidden(i, modelIndex, !showItem); |
| |
| if (!showItem) |
| channel->setIsActive(false); |
| } |
| } |
| |
| |
| |
| void FunctionTreeModel::ChannelGroup::setShowFilter(ShowFilter showFilter) |
| { |
| m_showFilter = showFilter; |
| applyShowFilter(); |
| } |
| |
| |
| |
| QString FunctionTreeModel::ChannelGroup::getIdName() const |
| { |
| QString tmpName = QString(m_name); |
| tmpName.remove(QChar(' '), Qt::CaseInsensitive); |
| tmpName = tmpName.toLower(); |
| |
| FunctionTreeModel::ChannelGroup *parentGroup = |
| dynamic_cast<FunctionTreeModel::ChannelGroup *>(getParent()); |
| if (parentGroup) { |
| return parentGroup->getIdName() + QString(".") + tmpName; |
| } |
| return tmpName; |
| } |
| |
| |
| |
| void FunctionTreeModel::ChannelGroup::setChildrenAllActive(bool active) |
| { |
| for (int i = 0; i < getChildCount(); i++) { |
| |
| FunctionTreeModel::Channel *channel = dynamic_cast<FunctionTreeModel::Channel *>(getChild(i)); |
| if (channel) { |
| channel->setIsActive(active); |
| continue; |
| } |
| |
| else { |
| FunctionTreeModel::ChannelGroup *channelGroup = dynamic_cast<FunctionTreeModel::ChannelGroup *>(getChild(i)); |
| if (channelGroup) { |
| channelGroup->setChildrenAllActive(active); |
| continue; |
| } |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| StageObjectChannelGroup::StageObjectChannelGroup(TStageObject *stageObject) |
| : m_stageObject(stageObject), m_plasticGroup() |
| { |
| m_stageObject->addRef(); |
| } |
| |
| |
| |
| StageObjectChannelGroup::~StageObjectChannelGroup() |
| { |
| m_stageObject->release(); |
| } |
| |
| |
| |
| QVariant StageObjectChannelGroup::data(int role) const |
| { |
| if (role == Qt::DisplayRole) { |
| string name = m_stageObject->getName(); |
| string id = m_stageObject->getId().toString(); |
| |
| return (name == id) ? QString::fromStdString(name) : QString::fromStdString(id + " (" + name + ")"); |
| |
| } else if (role == Qt::ForegroundRole) { |
| FunctionTreeModel *model = dynamic_cast<FunctionTreeModel *>(getModel()); |
| if (!model) |
| #if QT_VERSION >= 0x050000 |
| return QColor(Qt::black); |
| #else |
| return Qt::black; |
| #endif |
| FunctionTreeView *view = dynamic_cast<FunctionTreeView *>(model->getView()); |
| if (!view || !model->getCurrentStageObject()) |
| #if QT_VERSION >= 0x050000 |
| return QColor(Qt::black); |
| #else |
| return Qt::black; |
| #endif |
| TStageObjectId currentId = model->getCurrentStageObject()->getId(); |
| return m_stageObject->getId() == currentId ? view->getCurrentTextColor() : view->getTextColor(); |
| } else |
| return ChannelGroup::data(role); |
| } |
| |
| |
| |
| QString StageObjectChannelGroup::getShortName() const |
| { |
| return QString::fromStdString(m_stageObject->getName()); |
| } |
| |
| |
| |
| QString StageObjectChannelGroup::getLongName() const |
| { |
| return QString::fromStdString(m_stageObject->getFullName()); |
| } |
| |
| |
| |
| QString StageObjectChannelGroup::getIdName() const |
| { |
| return QString::fromStdString(m_stageObject->getId().toString()).toLower(); |
| } |
| |
| |
| |
| |
| |
| |
| |
| FxChannelGroup::FxChannelGroup(TFx *fx) |
| : m_fx(fx) |
| { |
| if (m_fx) |
| m_fx->addRef(); |
| } |
| |
| |
| |
| FxChannelGroup::~FxChannelGroup() |
| { |
| if (m_fx) |
| m_fx->release(); |
| m_fx = 0; |
| } |
| |
| |
| |
| QString FxChannelGroup::getShortName() const |
| { |
| return QString::fromStdWString(m_fx->getFxId()); |
| } |
| |
| |
| |
| QString FxChannelGroup::getLongName() const |
| { |
| return QString::fromStdWString(m_fx->getFxId()); |
| } |
| |
| |
| |
| QVariant FxChannelGroup::data(int role) const |
| { |
| if (role == Qt::DecorationRole) { |
| bool isAnimated = false; |
| TParamContainer *paramContainer = m_fx->getParams(); |
| int i; |
| for (i = 0; i < paramContainer->getParamCount(); i++) { |
| if (!paramContainer->getParam(i)->hasKeyframes()) |
| continue; |
| isAnimated = true; |
| break; |
| } |
| bool isOneChildActive = false; |
| for (i = 0; i < getChildCount(); i++) { |
| FunctionTreeModel::Channel *channel = dynamic_cast<FunctionTreeModel::Channel *>(getChild(i)); |
| if (!channel || !channel->isActive()) |
| continue; |
| isOneChildActive = true; |
| break; |
| } |
| if (isOneChildActive) { |
| static QIcon folderAnimOpen(":Resources/folderanim_open.png"); |
| static QIcon folderAnimClose(":Resources/folderanim_close.png"); |
| static QIcon folderOpen(":Resources/folder_open.png"); |
| static QIcon folderClose(":Resources/folder_close.png"); |
| |
| return isAnimated ? isOpen() ? folderAnimOpen : folderAnimClose : isOpen() ? folderOpen : folderClose; |
| } else { |
| static QIcon folderAnimOpen(":Resources/folderanim_open_off.png"); |
| static QIcon folderAnimClose(":Resources/folderanim_close_off.png"); |
| static QIcon folderOpen(":Resources/folder_open_off.png"); |
| static QIcon folderClose(":Resources/folder_close_off.png"); |
| |
| return isAnimated ? isOpen() ? folderAnimOpen : folderAnimClose : isOpen() ? folderOpen : folderClose; |
| } |
| } else if (role == Qt::DisplayRole) { |
| wstring name = m_fx->getName(); |
| wstring id = m_fx->getFxId(); |
| if (name == id) |
| return QString::fromStdWString(name); |
| else |
| return QString::fromStdWString(id + L" (" + name + L")"); |
| } else if (role == Qt::ForegroundRole) { |
| |
| FunctionTreeModel *model = dynamic_cast<FunctionTreeModel *>(getModel()); |
| if (!model) |
| #if QT_VERSION >= 0x050000 |
| return QColor(Qt::black); |
| #else |
| return Qt::black; |
| #endif |
| FunctionTreeView *view = dynamic_cast<FunctionTreeView *>(model->getView()); |
| if (!view) |
| #if QT_VERSION >= 0x050000 |
| return QColor(Qt::black); |
| #else |
| return Qt::black; |
| #endif |
| TFx *currentFx = model->getCurrentFx(); |
| return m_fx == currentFx ? view->getCurrentTextColor() : view->getTextColor(); |
| } else |
| return Item::data(role); |
| } |
| |
| |
| |
| QString FxChannelGroup::getIdName() const |
| { |
| return QString::fromStdWString(m_fx->getFxId()).toLower(); |
| } |
| |
| |
| |
| void FxChannelGroup::refresh() |
| { |
| TMacroFx *macroFx = dynamic_cast<TMacroFx *>(m_fx); |
| |
| int i, childrenCount = getChildCount(); |
| for (i = 0; i < childrenCount; ++i) { |
| FunctionTreeModel::ParamWrapper *wrap = |
| dynamic_cast<FunctionTreeModel::ParamWrapper *>(getChild(i)); |
| assert(wrap); |
| |
| TParam *param = 0; |
| { |
| TParamContainer *paramContainer = 0; |
| if (macroFx) { |
| const wstring &fxId = wrap->getFxId(); |
| TFx *subFx = macroFx->getFxById(fxId); |
| if (!subFx) |
| continue; |
| |
| paramContainer = subFx->getParams(); |
| } else |
| paramContainer = m_fx->getParams(); |
| |
| param = paramContainer->getParam(wrap->getParam()->getName()); |
| } |
| |
| assert(param); |
| wrap->setParam(param); |
| |
| ParamChannelGroup *paramGroup = dynamic_cast<ParamChannelGroup *>(wrap); |
| if (paramGroup) |
| paramGroup->refresh(); |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| ParamChannelGroup::ParamChannelGroup(TParam *param, const wstring &fxId, string ¶mName) |
| : ParamWrapper(param, fxId), ChannelGroup(param->hasUILabel() ? QString::fromStdString(param->getUILabel()) : QString::fromStdWString(TStringTable::translate(paramName))) |
| { |
| } |
| |
| |
| |
| void *ParamChannelGroup::getInternalPointer() const |
| { |
| return this->m_param.getPointer(); |
| } |
| |
| |
| |
| void ParamChannelGroup::refresh() |
| { |
| TParamSet *paramSet = dynamic_cast<TParamSet *>(m_param.getPointer()); |
| if (!paramSet) |
| return; |
| |
| int c, childrenCount = getChildCount(); |
| for (c = 0; c < childrenCount; ++c) { |
| FunctionTreeModel::ParamWrapper *wrap = |
| dynamic_cast<FunctionTreeModel::ParamWrapper *>(getChild(c)); |
| assert(wrap); |
| |
| TParamP currentParam = wrap->getParam(); |
| assert(currentParam); |
| |
| int p = paramSet->getParamIdx(wrap->getParam()->getName()); |
| assert(p < paramSet->getParamCount()); |
| |
| TParamP param = paramSet->getParam(p); |
| wrap->setParam(param); |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| QVariant SkVDChannelGroup::data(int role) const |
| { |
| if (role == Qt::ForegroundRole) { |
| |
| |
| |
| if (PlasticVertexSelection *vxSel = dynamic_cast<PlasticVertexSelection *>(TSelection::getCurrent())) |
| if (TStageObject *obj = static_cast<FunctionTreeModel *>(getModel())->getCurrentStageObject()) |
| if (obj == m_stageObjectGroup->m_stageObject) |
| if (const SkDP &sd = obj->getPlasticSkeletonDeformation()) { |
| int vIdx = *vxSel; |
| |
| if (vIdx >= 0 && sd->skeleton(vxSel->skeletonId())->vertex(vIdx).name() == getLongName()) |
| #if QT_VERSION >= 0x050000 |
| return QColor(Qt::red); |
| #else |
| return Qt::red; |
| #endif |
| } |
| |
| #if QT_VERSION >= 0x050000 |
| return QColor(Qt::black); |
| #else |
| return Qt::black; |
| #endif |
| } else |
| return ChannelGroup::data(role); |
| } |
| |
| |
| |
| |
| |
| |
| |
| FunctionTreeModel::Channel::Channel(FunctionTreeModel *model, TDoubleParam *param, |
| string paramNamePref, wstring fxId) |
| : ParamWrapper(param, fxId), m_model(model), m_group(0), m_isActive(false), m_paramNamePref(paramNamePref) |
| { |
| } |
| |
| |
| |
| FunctionTreeModel::Channel::~Channel() |
| { |
| m_model->onChannelDestroyed(this); |
| if (m_isActive) |
| getParam()->removeObserver(this); |
| } |
| |
| |
| |
| void *FunctionTreeModel::Channel::getInternalPointer() const |
| { |
| return this->m_param.getPointer(); |
| } |
| |
| |
| |
| bool FunctionTreeModel::Channel::isAnimated() const |
| { |
| return m_param->hasKeyframes(); |
| } |
| |
| |
| |
| QVariant FunctionTreeModel::Channel::data(int role) const |
| { |
| if (role == Qt::DecorationRole) { |
| static QIcon paramAnimOn(":Resources/paramanim_on.png"); |
| static QIcon paramAnimOff(":Resources/paramanim_off.png"); |
| static QIcon paramOn(":Resources/param_on.png"); |
| static QIcon paramOff(":Resources/param_off.png"); |
| |
| return m_param->hasKeyframes() ? isActive() ? paramAnimOn : paramAnimOff : isActive() ? paramOn : paramOff; |
| } else if (role == Qt::DisplayRole) { |
| if (m_param->hasUILabel()) { |
| return QString::fromStdString(m_param->getUILabel()); |
| } |
| string name = m_paramNamePref + m_param->getName(); |
| wstring translatedName = TStringTable::translate(name); |
| if (m_fxId.size() > 0) |
| return QString::fromStdWString(translatedName + L" (" + m_fxId + L")"); |
| return QString::fromStdWString(translatedName); |
| } else if (role == Qt::ForegroundRole) { |
| |
| FunctionTreeView *view = dynamic_cast<FunctionTreeView *>(m_model->m_view); |
| if (!view) |
| #if QT_VERSION >= 0x050000 |
| return QColor(Qt::black); |
| #else |
| return Qt::black; |
| #endif |
| return (isCurrent()) ? view->getCurrentTextColor() : view->getTextColor(); |
| } else |
| return TreeModel::Item::data(role); |
| } |
| |
| |
| |
| QString FunctionTreeModel::Channel::getShortName() const |
| { |
| if (m_param->hasUILabel()) { |
| return QString::fromStdString(m_param->getUILabel()); |
| } |
| string name = m_paramNamePref + m_param->getName(); |
| wstring translatedName = TStringTable::translate(name); |
| return QString::fromStdWString(translatedName); |
| } |
| |
| |
| |
| QString FunctionTreeModel::Channel::getLongName() const |
| { |
| QString name = getShortName(); |
| if (getChannelGroup()) |
| name = getChannelGroup()->getLongName() + " " + name; |
| return name; |
| } |
| |
| |
| |
| void FunctionTreeModel::Channel::setParam(const TParamP ¶m) |
| { |
| if (param.getPointer() == m_param.getPointer()) |
| return; |
| |
| TParamP oldParam = m_param; |
| m_param = param; |
| |
| if (m_isActive) { |
| oldParam->removeObserver(this); |
| param->addObserver(this); |
| } |
| } |
| |
| |
| |
| |
| QString FunctionTreeModel::Channel::getExprRefName() const |
| { |
| QString tmpName = |
| QString(QString::fromStdWString( |
| TStringTable::translate(m_paramNamePref + m_param->getName()))); |
| |
| StageObjectChannelGroup *stageGroup = |
| dynamic_cast<StageObjectChannelGroup *>(m_group); |
| if (stageGroup) { |
| if (tmpName == "N/S") |
| tmpName = "ns"; |
| else if (tmpName == "E/W") |
| tmpName = "ew"; |
| else if (tmpName == "Z") |
| tmpName = "z"; |
| else if (tmpName == "Rotation") |
| tmpName = "rot"; |
| else if (tmpName == "Scale H") |
| tmpName = "sx"; |
| else if (tmpName == "Scale V") |
| tmpName = "sy"; |
| else if (tmpName == "Shear H") |
| tmpName = "shx"; |
| else if (tmpName == "Shear V") |
| tmpName = "shy"; |
| else if (tmpName == "posPath") |
| tmpName = "path"; |
| else if (tmpName == "Scale") |
| tmpName = "sc"; |
| else |
| tmpName = tmpName.toLower(); |
| |
| return stageGroup->getIdName() + QString(".") + tmpName; |
| } |
| |
| |
| tmpName.remove(QChar(' '), Qt::CaseInsensitive); |
| tmpName.remove(QChar('/')); |
| tmpName = tmpName.toLower(); |
| |
| FunctionTreeModel::ChannelGroup *parentGroup = |
| dynamic_cast<FunctionTreeModel::ChannelGroup *>(getParent()); |
| if (parentGroup) { |
| return QString("fx.") + parentGroup->getIdName() + QString(".") + tmpName; |
| } else |
| return ""; |
| } |
| |
| |
| |
| void FunctionTreeModel::Channel::setIsActive(bool active) |
| { |
| if (active == m_isActive) |
| return; |
| |
| m_isActive = active; |
| m_model->refreshActiveChannels(); |
| if (m_isActive) { |
| getParam()->addObserver(this); |
| |
| if (!m_model->m_currentChannel) { |
| setIsCurrent(true); |
| m_model->emitCurveSelected(getParam()); |
| } |
| } else { |
| getParam()->removeObserver(this); |
| if (isCurrent()) { |
| setIsCurrent(false); |
| m_model->emitCurveSelected(0); |
| } |
| } |
| |
| m_model->emitDataChanged(this); |
| } |
| |
| |
| |
| bool FunctionTreeModel::Channel::isCurrent() const |
| { |
| return m_model->m_currentChannel == this; |
| } |
| |
| |
| |
| void FunctionTreeModel::Channel::setIsCurrent(bool current) |
| { |
| Channel *oldCurrent = m_model->m_currentChannel; |
| if (current) { |
| |
| if (oldCurrent == this) |
| return; |
| m_model->m_currentChannel = this; |
| |
| |
| FxChannelGroup *fxGroup = dynamic_cast<FxChannelGroup *>(m_group); |
| if (fxGroup && m_model->getFxHandle()) { |
| m_model->getFxHandle()->setFx(fxGroup->getFx()); |
| } |
| |
| else { |
| StageObjectChannelGroup *stageObjectGroup = dynamic_cast<StageObjectChannelGroup *>(m_group); |
| if (stageObjectGroup && m_model->getObjectHandle()) { |
| m_model->getObjectHandle()->setObjectId(stageObjectGroup->getStageObject()->getId()); |
| } |
| } |
| |
| |
| if (!m_isActive) { |
| m_isActive = true; |
| m_model->refreshActiveChannels(); |
| getParam()->addObserver(this); |
| } |
| |
| if (oldCurrent) |
| m_model->emitDataChanged(oldCurrent); |
| m_model->emitDataChanged(this); |
| m_model->emitCurveSelected(getParam()); |
| |
| m_model->emitCurrentChannelChanged(this); |
| } else { |
| |
| if (oldCurrent != this) |
| return; |
| m_model->m_currentChannel = 0; |
| |
| m_model->emitDataChanged(this); |
| } |
| } |
| |
| |
| |
| bool FunctionTreeModel::Channel::isHidden() const |
| { |
| return getChannelGroup()->getShowFilter() == ChannelGroup::ShowAnimatedChannels && |
| !getParam()->hasKeyframes(); |
| } |
| |
| |
| |
| void FunctionTreeModel::Channel::onChange(const TParamChange &ch) |
| { |
| m_model->onChange(ch); |
| } |
| |
| |
| |
| |
| |
| |
| |
| FunctionTreeModel::FunctionTreeModel(FunctionTreeView *parent) |
| : TreeModel(parent), m_currentChannel(0), m_stageObjects(0), m_fxs(0), m_currentStageObject(0), m_currentFx(0), m_paramsChanged(false) |
| { |
| } |
| |
| |
| |
| FunctionTreeModel::~FunctionTreeModel() |
| { |
| |
| |
| setRootItem(0); |
| if (m_currentFx) |
| m_currentFx->release(); |
| } |
| |
| |
| |
| void FunctionTreeModel::refreshData(TXsheet *xsh) |
| { |
| m_activeChannels.clear(); |
| Channel *currentChannel = m_currentChannel; |
| |
| beginRefresh(); |
| { |
| if (!getRootItem()) { |
| setRootItem(new ChannelGroup("Root")); |
| |
| if (xsh) { |
| getRootItem()->appendChild(m_stageObjects = new ChannelGroup("Stage")); |
| getRootItem()->appendChild(m_fxs = new ChannelGroup("FX")); |
| |
| assert(getRootItem()->getChildCount() == 2); |
| assert(getRootItem()->getChild(0) == m_stageObjects); |
| assert(getRootItem()->getChild(1) == m_fxs); |
| } |
| } |
| |
| if (xsh) { |
| refreshStageObjects(xsh); |
| refreshFxs(xsh); |
| } |
| |
| refreshActiveChannels(); |
| } |
| endRefresh(); |
| |
| if (m_currentChannel != currentChannel) |
| emit curveSelected(0); |
| } |
| |
| |
| |
| void FunctionTreeModel::refreshStageObjects(TXsheet *xsh) |
| { |
| static const int channelIds[TStageObject::T_ChannelCount] = { |
| TStageObject::T_X, |
| TStageObject::T_Y, |
| TStageObject::T_Z, |
| TStageObject::T_SO, |
| TStageObject::T_Path, |
| TStageObject::T_Angle, |
| TStageObject::T_ScaleX, |
| TStageObject::T_ScaleY, |
| TStageObject::T_Scale, |
| TStageObject::T_ShearX, |
| TStageObject::T_ShearY}; |
| |
| |
| QList<TreeModel::Item *> newItems; |
| TStageObjectTree *ptree = xsh->getStageObjectTree(); |
| |
| int i, iCount = ptree->getStageObjectCount(); |
| for (i = 0; i < iCount; ++i) { |
| TStageObject *pegbar = ptree->getStageObject(i); |
| TStageObjectId id = pegbar->getId(); |
| if (id.isColumn() && xsh->isColumnEmpty(id.getIndex())) |
| continue; |
| |
| newItems.push_back(new StageObjectChannelGroup(pegbar)); |
| } |
| |
| |
| |
| m_stageObjects->setChildren(newItems); |
| |
| |
| iCount = newItems.size(); |
| for (i = 0; i < iCount; ++i) { |
| StageObjectChannelGroup *pegbarItem = |
| dynamic_cast<StageObjectChannelGroup *>(newItems[i]); |
| |
| TStageObject *stageObject = pegbarItem->getStageObject(); |
| |
| |
| int j, jCount = TStageObject::T_ChannelCount; |
| |
| for (j = 0; j < jCount; ++j) { |
| TDoubleParam *param = stageObject->getParam((TStageObject::Channel)channelIds[j]); |
| Channel *channel = new Channel(this, param); |
| |
| pegbarItem->appendChild(channel); |
| channel->setChannelGroup(pegbarItem); |
| } |
| |
| pegbarItem->applyShowFilter(); |
| } |
| |
| |
| refreshPlasticDeformations(); |
| } |
| |
| |
| |
| void FunctionTreeModel::refreshFxs(TXsheet *xsh) |
| { |
| std::vector<TFx *> fxs; |
| xsh->getFxDag()->getFxs(fxs); |
| for (int i = 0; i < xsh->getColumnCount(); i++) { |
| TXshZeraryFxColumn *zc = |
| dynamic_cast<TXshZeraryFxColumn *>(xsh->getColumn(i)); |
| if (!zc) |
| continue; |
| fxs.push_back(zc->getZeraryColumnFx()->getZeraryFx()); |
| } |
| |
| |
| for (int j = 1; j < (int)fxs.size(); j++) { |
| int index = j; |
| while (index > 0 && QString::localeAwareCompare(QString::fromStdWString(fxs[index - 1]->getFxId()), QString::fromStdWString(fxs[index]->getFxId())) > 0) { |
| std::swap(fxs[index - 1], fxs[index]); |
| index = index - 1; |
| } |
| } |
| |
| QList<TreeModel::Item *> newItems; |
| int i; |
| for (i = 0; i < (int)fxs.size(); i++) { |
| TFx *fx = fxs[i]; |
| if (!fx) |
| continue; |
| TParamContainer *params = fx->getParams(); |
| bool hasChannel = false; |
| int j; |
| for (j = 0; j < params->getParamCount(); j++) |
| if (0 != dynamic_cast<TDoubleParam *>(params->getParam(j)) || |
| 0 != dynamic_cast<TPointParam *>(params->getParam(j)) || |
| 0 != dynamic_cast<TRangeParam *>(params->getParam(j)) || |
| 0 != dynamic_cast<TPixelParam *>(params->getParam(j))) { |
| hasChannel = true; |
| break; |
| } |
| if (hasChannel) |
| newItems.push_back(new FxChannelGroup(fxs[i])); |
| } |
| m_fxs->setChildren(newItems); |
| |
| |
| for (i = 0; i < (int)newItems.size(); i++) { |
| TreeModel::Item *item = newItems[i]; |
| FxChannelGroup *fxItem = dynamic_cast<FxChannelGroup *>(item); |
| assert(fxItem); |
| if (!fxItem) |
| continue; |
| TFx *fx = fxItem->getFx(); |
| assert(fx); |
| if (!fx) |
| continue; |
| TMacroFx *macroFx = dynamic_cast<TMacroFx *>(fx); |
| if (macroFx) { |
| const vector<TFxP> ¯oFxs = macroFx->getFxs(); |
| int j; |
| for (j = 0; j < (int)macroFxs.size(); j++) { |
| TParamContainer *params = macroFxs[j]->getParams(); |
| addChannels(macroFxs[j].getPointer(), fxItem, params); |
| } |
| } else { |
| TParamContainer *params = fx->getParams(); |
| addChannels(fx, fxItem, params); |
| } |
| fxItem->applyShowFilter(); |
| } |
| } |
| |
| |
| |
| void FunctionTreeModel::refreshPlasticDeformations() |
| { |
| |
| int i, iCount = m_stageObjects->getChildCount(); |
| for (i = 0; i < iCount; ++i) { |
| |
| StageObjectChannelGroup *stageItem = |
| static_cast<StageObjectChannelGroup *>(m_stageObjects->getChild(i)); |
| |
| TStageObject *stageObject = stageItem->getStageObject(); |
| |
| const PlasticSkeletonDeformationP &sd = stageObject->getPlasticSkeletonDeformation(); |
| FunctionTreeModel::ChannelGroup *&plasticGroup = stageItem->m_plasticGroup; |
| |
| if (sd || plasticGroup) { |
| if (!plasticGroup) { |
| |
| plasticGroup = new ChannelGroup("Plastic Skeleton"); |
| stageItem->appendChild(plasticGroup); |
| } |
| |
| |
| QList<TreeModel::Item *> plasticItems; |
| |
| if (sd) { |
| SkD::vd_iterator vdt, vdEnd; |
| sd->vertexDeformations(vdt, vdEnd); |
| |
| for (; vdt != vdEnd; ++vdt) { |
| const QString *str = (*vdt).first; |
| |
| QList<TreeModel::Item *>::iterator it = std::lower_bound( |
| plasticItems.begin(), plasticItems.end(), |
| *str, SkVDChannelGroup::compareStr); |
| |
| plasticItems.insert(it, new SkVDChannelGroup(str, stageItem)); |
| } |
| |
| |
| { |
| Channel *skelIdsChannel = new Channel(this, sd->skeletonIdsParam().getPointer()); |
| |
| plasticItems.insert(plasticItems.begin(), skelIdsChannel); |
| skelIdsChannel->setChannelGroup(plasticGroup); |
| } |
| } |
| |
| if (plasticItems.empty()) |
| plasticGroup->setIsOpen(false); |
| |
| |
| |
| plasticGroup->setChildren(plasticItems); |
| |
| int pi, piCount = plasticItems.size(); |
| for (pi = 0; pi != piCount; ++pi) |
| { |
| SkVDChannelGroup *vxGroup = dynamic_cast<SkVDChannelGroup *>(plasticItems[pi]); |
| if (!vxGroup) |
| continue; |
| |
| SkVD *skvd = sd->vertexDeformation(vxGroup->ChannelGroup::getShortName()); |
| |
| for (int k = 0; k < SkVD::PARAMS_COUNT; ++k) { |
| |
| Channel *channel = new Channel(this, skvd->m_params[k].getPointer()); |
| channel->setChannelGroup(vxGroup); |
| |
| vxGroup->appendChild(channel); |
| } |
| |
| vxGroup->applyShowFilter(); |
| } |
| |
| plasticGroup->applyShowFilter(); |
| } |
| } |
| } |
| |
| |
| |
| void FunctionTreeModel::addParameter( |
| ChannelGroup *group, |
| const std::string &prefixString, |
| const std::wstring &fxId, |
| TParam *param) |
| { |
| if (TDoubleParam *dp = dynamic_cast<TDoubleParam *>(param)) { |
| Channel *channel = new Channel(this, dp, prefixString, fxId); |
| |
| group->appendChild(channel); |
| channel->setChannelGroup(group); |
| } else if (dynamic_cast<TPointParam *>(param) || |
| dynamic_cast<TRangeParam *>(param) || |
| dynamic_cast<TPixelParam *>(param)) { |
| TParamSet *paramSet = dynamic_cast<TParamSet *>(param); |
| assert(paramSet); |
| |
| std::string paramName = prefixString + param->getName(); |
| |
| ChannelGroup *paramChannel = new ParamChannelGroup(param, fxId, paramName); |
| group->appendChild(paramChannel); |
| |
| TPixelParam *pixParam = dynamic_cast<TPixelParam *>(param); |
| |
| int p, paramCount = paramSet->getParamCount(); |
| for (p = 0; p != paramCount; ++p) { |
| TDoubleParam *dp = dynamic_cast<TDoubleParam *>(paramSet->getParam(p).getPointer()); |
| if (!dp || (pixParam && !pixParam->isMatteEnabled() && p == paramCount - 1)) |
| continue; |
| |
| Channel *channel = new Channel(this, dp, "", fxId); |
| |
| paramChannel->appendChild(channel); |
| channel->setChannelGroup(group); |
| } |
| } |
| } |
| |
| |
| |
| void FunctionTreeModel::addChannels(TFx *fx, ChannelGroup *groupItem, TParamContainer *params) |
| { |
| FxChannelGroup *fxItem = static_cast<FxChannelGroup *>(groupItem); |
| |
| wstring fxId = L""; |
| TMacroFx *macro = dynamic_cast<TMacroFx *>(fxItem->getFx()); |
| if (macro) |
| fxId = fx->getFxId(); |
| |
| const string ¶mNamePref = fx->getFxType() + "."; |
| |
| int p, pCount = params->getParamCount(); |
| for (p = 0; p != pCount; ++p) |
| addParameter(fxItem, paramNamePref, fxId, params->getParam(p)); |
| } |
| |
| |
| |
| void FunctionTreeModel::addActiveChannels(TreeModel::Item *item) |
| { |
| assert(item); |
| |
| if (Channel *channel = dynamic_cast<Channel *>(item)) { |
| if (channel->isActive()) |
| m_activeChannels.push_back(channel); |
| } else |
| for (int i = 0; i < item->getChildCount(); i++) |
| addActiveChannels(item->getChild(i)); |
| } |
| |
| |
| |
| void FunctionTreeModel::refreshActiveChannels() |
| { |
| m_activeChannels.clear(); |
| |
| if (m_stageObjects) |
| addActiveChannels(m_stageObjects); |
| |
| if (m_fxs) |
| addActiveChannels(m_fxs); |
| } |
| |
| |
| |
| void FunctionTreeModel::onChannelDestroyed(Channel *channel) |
| { |
| if (channel == m_currentChannel) |
| m_currentChannel = 0; |
| } |
| |
| |
| |
| FunctionTreeModel::Channel *FunctionTreeModel::getActiveChannel(int index) const |
| { |
| if (index < 0 || index >= (int)m_activeChannels.size()) |
| return 0; |
| else |
| return m_activeChannels[index]; |
| } |
| |
| |
| |
| int FunctionTreeModel::getColumnIndexByCurve(TDoubleParam *param) const |
| { |
| for (int i = 0; i < (int)m_activeChannels.size(); i++) { |
| if (m_activeChannels[i]->getParam() == param) |
| return i; |
| } |
| return -1; |
| } |
| |
| |
| |
| FunctionTreeModel::ChannelGroup *FunctionTreeModel::getStageObjectChannel(int index) const |
| { |
| if (index < 0 || index >= (int)m_stageObjects->getChildCount()) |
| return 0; |
| else |
| return dynamic_cast<FunctionTreeModel::ChannelGroup *>(m_stageObjects->getChild(index)); |
| } |
| |
| |
| |
| FunctionTreeModel::ChannelGroup *FunctionTreeModel::getFxChannel(int index) const |
| { |
| if (index < 0 || index >= (int)m_fxs->getChildCount()) |
| return 0; |
| else |
| return dynamic_cast<FunctionTreeModel::ChannelGroup *>(m_fxs->getChild(index)); |
| } |
| |
| |
| |
| void FunctionTreeModel::onChange(const TParamChange &tpc) |
| { |
| if (!m_paramsChanged) { |
| m_paramsChanged = true; |
| |
| struct Func : public TFunctorInvoker::BaseFunctor { |
| FunctionTreeModel *m_obj; |
| const TParamChange *m_tpc; |
| |
| Func(FunctionTreeModel *obj, const TParamChange *tpc) : m_obj(obj), m_tpc(tpc) {} |
| void operator()() { m_obj->onParamChange(m_tpc->m_dragging); } |
| }; |
| |
| QMetaObject::invokeMethod(TFunctorInvoker::instance(), "invoke", Qt::QueuedConnection, |
| Q_ARG(void *, new Func(this, &tpc))); |
| } |
| } |
| |
| |
| |
| void FunctionTreeModel::onParamChange(bool isDragging) |
| { |
| m_paramsChanged = false; |
| |
| emit curveChanged(isDragging); |
| } |
| |
| |
| |
| void FunctionTreeModel::resetAll() |
| { |
| #if QT_VERSION >= 0x050000 |
| beginResetModel(); |
| #endif |
| m_activeChannels.clear(); |
| setRootItem(0); |
| m_stageObjects = 0; |
| m_fxs = 0; |
| #if QT_VERSION < 0x050000 |
| reset(); |
| #endif |
| |
| beginRefresh(); |
| refreshActiveChannels(); |
| endRefresh(); |
| |
| m_currentChannel = 0; |
| |
| #if QT_VERSION >= 0x050000 |
| endResetModel(); |
| #endif |
| } |
| |
| |
| |
| void FunctionTreeModel::setCurrentFx(TFx *fx) |
| { |
| TZeraryColumnFx *zcfx = dynamic_cast<TZeraryColumnFx *>(fx); |
| if (zcfx) |
| fx = zcfx->getZeraryFx(); |
| if (fx != m_currentFx) { |
| if (fx) |
| fx->addRef(); |
| if (m_currentFx) |
| m_currentFx->release(); |
| m_currentFx = fx; |
| } |
| } |
| |
| |
| |
| void FunctionTreeModel::applyShowFilters() |
| { |
| |
| |
| |
| |
| |
| |
| if (m_stageObjects) { |
| int so, soCount = m_stageObjects->getChildCount(); |
| for (so = 0; so != soCount; ++so) |
| getStageObjectChannel(so)->applyShowFilter(); |
| } |
| |
| if (m_fxs) { |
| int fx, fxCount = m_fxs->getChildCount(); |
| for (fx = 0; fx != fxCount; ++fx) |
| getFxChannel(fx)->applyShowFilter(); |
| } |
| } |
| |
| |
| |
| void FunctionTreeModel::addParameter( |
| TParam *parameter, const TFilePath &folder) |
| { |
| struct locals { |
| static void locateExistingRoot(ChannelGroup *&root, TFilePath &fp) |
| { |
| std::wstring firstName; |
| TFilePath tempFp; |
| |
| while (!fp.isEmpty()) { |
| |
| fp.split(firstName, tempFp); |
| |
| |
| int c, cCount = root->getChildCount(); |
| for (c = 0; c != cCount; ++c) { |
| if (ChannelGroup *group = dynamic_cast<ChannelGroup *>(root->getChild(c))) { |
| if (group->getShortName().toStdWString() == firstName) { |
| root = group, fp = tempFp; |
| break; |
| } |
| } |
| } |
| |
| if (c == cCount) |
| break; |
| } |
| } |
| |
| static void addFolders(ChannelGroup *&group, TFilePath &fp) |
| { |
| std::wstring firstName; |
| TFilePath tempFp; |
| |
| while (!fp.isEmpty()) { |
| fp.split(firstName, tempFp); |
| |
| ChannelGroup *newGroup = new ChannelGroup(QString::fromStdWString(firstName)); |
| group->appendChild(newGroup); |
| |
| group = newGroup, fp = tempFp; |
| } |
| } |
| }; |
| |
| |
| ChannelGroup *group = static_cast<ChannelGroup *>(getRootItem()); |
| assert(group); |
| |
| TFilePath path = folder; |
| locals::locateExistingRoot(group, path); |
| |
| |
| if (!path.isEmpty()) |
| locals::addFolders(group, path); |
| |
| assert(path.isEmpty()); |
| |
| |
| addParameter(group, "", L"", parameter); |
| } |
| |
| |
| |
| |
| |
| |
| |
| FunctionTreeView::FunctionTreeView(FunctionViewer *parent) |
| : TreeView(parent), m_scenePath(), m_clickedItem(0), m_draggingChannel(0) |
| { |
| assert(parent); |
| |
| setModel(new FunctionTreeModel(this)); |
| |
| setObjectName("FunctionEditorTree"); |
| setSelectionMode(QAbstractItemView::NoSelection); |
| |
| connect( |
| this, SIGNAL(pressed(const QModelIndex &)), |
| this, SLOT(onActivated(const QModelIndex &))); |
| |
| setFocusPolicy(Qt::NoFocus); |
| setIndentation(14); |
| setAlternatingRowColors(true); |
| } |
| |
| |
| |
| void FunctionTreeView::onActivated(const QModelIndex &index) |
| { |
| enum { |
| NO_CHANNELS = 0x0, |
| ACTIVE_CHANNELS = 0x1, |
| INACTIVE_CHANNELS = 0x2, |
| HAS_CHANNELS = ACTIVE_CHANNELS | INACTIVE_CHANNELS |
| }; |
| |
| if (!index.isValid()) |
| return; |
| |
| FunctionTreeModel *ftModel = (FunctionTreeModel *)model(); |
| if (!ftModel) |
| return; |
| |
| std::vector<FunctionTreeModel::Channel *> childChannels; |
| std::vector<FunctionTreeModel::ChannelGroup *> channelGroups; |
| |
| |
| int activeFlag = NO_CHANNELS; |
| |
| TreeModel::Item *item = static_cast<TreeModel::Item *>(index.internalPointer()); |
| if (item) { |
| int c, cCount = item->getChildCount(); |
| for (c = 0; c != cCount; ++c) { |
| FunctionTreeModel::Channel *channel = |
| dynamic_cast<FunctionTreeModel::Channel *>(item->getChild(c)); |
| |
| if (!channel) { |
| FunctionTreeModel::ChannelGroup *channelGroup = |
| dynamic_cast<FunctionTreeModel::ChannelGroup *>(item->getChild(c)); |
| if (!channelGroup) |
| continue; |
| channelGroups.push_back(channelGroup); |
| continue; |
| } |
| if (channel->isHidden()) |
| continue; |
| |
| childChannels.push_back(channel); |
| |
| activeFlag |= (channel->isActive() ? ACTIVE_CHANNELS : INACTIVE_CHANNELS); |
| } |
| } |
| |
| |
| bool someInactiveChannels = (activeFlag != ACTIVE_CHANNELS); |
| |
| if (someInactiveChannels && !isExpanded(index)) { |
| setExpanded(index, true); |
| ftModel->onExpanded(index); |
| } |
| |
| if (item) { |
| if (!childChannels.empty()) { |
| |
| int c, cCount = childChannels.size(); |
| for (c = 0; c != cCount; ++c) |
| childChannels[c]->setIsActive(someInactiveChannels); |
| |
| for (int i = 0; i < (int)channelGroups.size(); i++) |
| channelGroups[i]->setChildrenAllActive(someInactiveChannels); |
| |
| update(); |
| } else { |
| |
| int c, cCount = item->getChildCount(); |
| for (c = 0; c != cCount; ++c) |
| onActivated(item->getChild(c)->createIndex()); |
| } |
| } |
| } |
| |
| |
| |
| void FunctionTreeView::onClick(TreeModel::Item *item, const QPoint &itemPos, QMouseEvent *e) |
| { |
| m_draggingChannel = 0; |
| FunctionTreeModel::Channel *channel = dynamic_cast<FunctionTreeModel::Channel *>(item); |
| FxChannelGroup *fxChannelGroup = dynamic_cast<FxChannelGroup *>(item); |
| StageObjectChannelGroup *stageObjectChannelGroup = dynamic_cast<StageObjectChannelGroup *>(item); |
| |
| m_clickedItem = channel; |
| |
| if (channel) { |
| fxChannelGroup = dynamic_cast<FxChannelGroup *>(channel->getParent()); |
| stageObjectChannelGroup = dynamic_cast<StageObjectChannelGroup *>(channel->getParent()); |
| |
| int x = itemPos.x(); |
| if (x >= 20) |
| channel->setIsCurrent(true); |
| else if (0 <= x && x < 20) { |
| channel->setIsActive((e->button() == Qt::RightButton) ? true : !channel->isActive()); |
| update(); |
| } |
| } |
| |
| if (fxChannelGroup) { |
| TFx *fx = fxChannelGroup->getFx(); |
| emit switchCurrentFx(fx); |
| } |
| |
| if (stageObjectChannelGroup) { |
| TStageObject *obj = stageObjectChannelGroup->getStageObject(); |
| emit switchCurrentObject(obj); |
| } |
| } |
| |
| |
| |
| void FunctionTreeView::onMidClick(TreeModel::Item *item, const QPoint &itemPos, QMouseEvent *e) |
| { |
| FunctionTreeModel::Channel *channel = |
| dynamic_cast<FunctionTreeModel::Channel *>(item); |
| if (channel && e->button() == Qt::MidButton) { |
| m_draggingChannel = channel; |
| m_dragStartPosition = e->pos(); |
| } else |
| m_draggingChannel = 0; |
| } |
| |
| |
| |
| void FunctionTreeView::onDrag(TreeModel::Item *item, const QPoint &itemPos, QMouseEvent *e) |
| { |
| |
| if ((e->buttons() & Qt::MidButton) && |
| m_draggingChannel && |
| (e->pos() - m_dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) { |
| QDrag *drag = new QDrag(this); |
| QMimeData *mimeData = new QMimeData; |
| mimeData->setText(m_draggingChannel->getExprRefName()); |
| drag->setMimeData(mimeData); |
| static const QPixmap cursorPixmap(":Resources/dragcursor_exp_text.png"); |
| drag->setDragCursor(cursorPixmap, Qt::MoveAction); |
| Qt::DropAction dropAction = drag->exec(); |
| return; |
| } |
| |
| FunctionTreeModel::Channel *channel = dynamic_cast<FunctionTreeModel::Channel *>(item); |
| if (!channel || !m_clickedItem) |
| return; |
| |
| |
| |
| QModelIndex i0 = channel->createIndex(), i1 = m_clickedItem->createIndex(); |
| if (!i0.isValid() || !i1.isValid() || i0.parent() != i1.parent()) |
| return; |
| |
| if (i0.row() > i1.row()) |
| tswap(i0, i1); |
| |
| FunctionTreeModel *md = static_cast<FunctionTreeModel *>(model()); |
| |
| bool active = m_clickedItem->isActive(); |
| |
| for (int row = i0.row(); row <= i1.row(); ++row) { |
| if (isRowHidden(row, i0.parent())) |
| continue; |
| |
| QModelIndex index = md->index(row, 0, i0.parent()); |
| |
| TreeModel::Item *chItem = static_cast<TreeModel::Item *>(index.internalPointer()); |
| FunctionTreeModel::Channel *ch = dynamic_cast<FunctionTreeModel::Channel *>(chItem); |
| |
| if (ch && ch->isActive() != active) { |
| ch->setIsActive(active); |
| update(); |
| } |
| } |
| } |
| |
| |
| |
| void FunctionTreeView::onRelease() |
| { |
| m_clickedItem = 0; |
| } |
| |
| |
| |
| void FunctionTreeView::openContextMenu(TreeModel::Item *item, const QPoint &globalPos) |
| { |
| if (FunctionTreeModel::Channel *channel = dynamic_cast<FunctionTreeModel::Channel *>(item)) |
| openContextMenu(channel, globalPos); |
| else if (FunctionTreeModel::ChannelGroup *group = dynamic_cast<FunctionTreeModel::ChannelGroup *>(item)) |
| openContextMenu(group, globalPos); |
| } |
| |
| |
| |
| void FunctionTreeView::openContextMenu(FunctionTreeModel::Channel *channel, const QPoint &globalPos) |
| { |
| assert(channel); |
| |
| QWidget *pw = dynamic_cast<QWidget *>(parentWidget()); |
| if (!pw) |
| return; |
| |
| FunctionViewer *fv = dynamic_cast<FunctionViewer *>(pw->parentWidget()); |
| |
| if (!fv) { |
| assert(fv); |
| return; |
| } |
| |
| QMenu menu; |
| |
| QAction saveCurveAction(tr("Save Curve"), 0); |
| QAction loadCurveAction(tr("Load Curve"), 0); |
| QAction exportDataAction(tr("Export Data"), 0); |
| menu.addAction(&saveCurveAction); |
| menu.addAction(&loadCurveAction); |
| menu.addAction(&exportDataAction); |
| |
| QAction *action = menu.exec(globalPos); |
| |
| TDoubleParam *curve = channel->getParam(); |
| |
| if (action == &saveCurveAction) |
| fv->emitIoCurve((int)FunctionViewer::eSaveCurve, curve, ""); |
| else if (action == &loadCurveAction) |
| fv->emitIoCurve((int)FunctionViewer::eLoadCurve, curve, ""); |
| else if (action == &exportDataAction) |
| fv->emitIoCurve((int)FunctionViewer::eExportCurve, curve, channel->getLongName().toStdString()); |
| } |
| |
| |
| |
| void FunctionTreeView::openContextMenu(FunctionTreeModel::ChannelGroup *group, const QPoint &globalPos) |
| { |
| assert(group); |
| |
| QMenu menu; |
| |
| QAction showAnimateOnly(tr("Show Animated Only"), 0); |
| QAction showAll(tr("Show All"), 0); |
| menu.addAction(&showAnimateOnly); |
| menu.addAction(&showAll); |
| |
| |
| QAction *action = menu.exec(globalPos); |
| |
| if (action != &showAll && action != &showAnimateOnly) |
| return; |
| |
| FunctionTreeModel::ChannelGroup::ShowFilter showFilter = |
| (action == &showAll) ? FunctionTreeModel::ChannelGroup::ShowAllChannels : FunctionTreeModel::ChannelGroup::ShowAnimatedChannels; |
| |
| expand(group->createIndex()); |
| group->setShowFilter(showFilter); |
| } |
| |
| |
| |
| void FunctionTreeView::updateAll() |
| { |
| FunctionTreeModel *functionTreeModel = dynamic_cast<FunctionTreeModel *>(model()); |
| assert(functionTreeModel); |
| |
| functionTreeModel->applyShowFilters(); |
| update(); |
| } |
| |
| |
| |
| |
| void FunctionTreeView::displayAnimatedChannels() |
| { |
| FunctionTreeModel *functionTreeModel = dynamic_cast<FunctionTreeModel *>(model()); |
| assert(functionTreeModel); |
| int i; |
| for (i = 0; i < functionTreeModel->getStageObjectsChannelCount(); i++) |
| functionTreeModel->getStageObjectChannel(i)->displayAnimatedChannels(); |
| for (i = 0; i < functionTreeModel->getFxsChannelCount(); i++) |
| functionTreeModel->getFxChannel(i)->displayAnimatedChannels(); |
| update(); |
| } |
| |
| |
| |
| |
| void FunctionTreeModel::ChannelGroup::displayAnimatedChannels() |
| { |
| int itemCount = getChildCount(); |
| int i; |
| |
| for (i = 0; i < itemCount; i++) { |
| FunctionTreeModel::Channel *channel = dynamic_cast<FunctionTreeModel::Channel *>(getChild(i)); |
| if (!channel) { |
| FunctionTreeModel::ChannelGroup *channelGroup = |
| dynamic_cast<FunctionTreeModel::ChannelGroup *>(getChild(i)); |
| if (!channelGroup) |
| continue; |
| |
| channelGroup->displayAnimatedChannels(); |
| continue; |
| } |
| channel->setIsActive(channel->getParam()->hasKeyframes()); |
| } |
| } |
| |