| |
| |
| #include "toonzqt/functionviewer.h" |
| |
| |
| #include "toonzqt/functionselection.h" |
| #include "toonzqt/functionpanel.h" |
| #include "toonzqt/functiontreeviewer.h" |
| #include "toonzqt/functionsheet.h" |
| #include "toonzqt/functionsegmentviewer.h" |
| #include "toonzqt/functiontoolbar.h" |
| #include "toonzqt/swatchviewer.h" |
| #include "toonzqt/dvscrollwidget.h" |
| |
| |
| #include "toonz/tstageobjecttree.h" |
| #include "toonz/txsheet.h" |
| #include "toonz/txsheethandle.h" |
| #include "toonz/tobjecthandle.h" |
| #include "toonz/tfxhandle.h" |
| #include "toonz/tcolumnhandle.h" |
| #include "toonz/fxdag.h" |
| #include "toonz/txshzeraryfxcolumn.h" |
| #include "toonz/tcolumnfx.h" |
| #include "toonz/toonzscene.h" |
| #include "toonz/tproject.h" |
| #include "toonz/tscenehandle.h" |
| #include "toonz/sceneproperties.h" |
| |
| |
| #include "tparamcontainer.h" |
| #include "tunit.h" |
| |
| |
| #include "tstopwatch.h" |
| |
| |
| #include <QPainter> |
| #include <QMouseEvent> |
| #include <QWheelEvent> |
| #include <QBoxLayout> |
| #include <QPushButton> |
| #include <QStackedWidget> |
| #include <QLabel> |
| #include <QToolBar> |
| #include <QAction> |
| |
| using namespace DVGui; |
| |
| |
| |
| |
| |
| |
| |
| #if QT_VERSION >= 0x050500 |
| FunctionViewer::FunctionViewer(QWidget *parent, Qt::WindowFlags flags) |
| #else |
| FunctionViewer::FunctionViewer(QWidget *parent, Qt::WFlags flags) |
| #endif |
| : QSplitter(parent), m_xshHandle(0), m_frameHandle(0), m_objectHandle(0), m_fxHandle(0), m_columnHandle(0), m_curve(0), m_selection(new FunctionSelection()), m_sceneHandle(0) |
| { |
| setObjectName("FunctionEditor"); |
| |
| |
| m_localFrame.setFrame(0); |
| setFocusPolicy(Qt::NoFocus); |
| |
| m_treeView = new FunctionTreeView(this); |
| m_functionGraph = new FunctionPanel(this); |
| m_numericalColumns = new FunctionSheet(); |
| m_toolbar = new FunctionToolbar; |
| m_segmentViewer = new FunctionSegmentViewer(this, m_numericalColumns, m_functionGraph); |
| QWidget *leftPanel = new QWidget(); |
| QWidget *rightPanel = new QWidget(); |
| |
| |
| m_treeView->resize(150, m_treeView->size().height()); |
| m_treeView->setMinimumWidth(0); |
| |
| FunctionTreeModel *ftModel = |
| dynamic_cast<FunctionTreeModel *>(m_treeView->model()); |
| m_functionGraph->setModel(ftModel); |
| m_numericalColumns->setModel(ftModel); |
| |
| m_functionGraph->setSelection(getSelection()); |
| m_numericalColumns->setSelection(getSelection()); |
| |
| m_numericalColumns->setViewer(this); |
| |
| m_toolbar->setSelection(m_selection); |
| m_toolbar->setFocusPolicy(Qt::NoFocus); |
| |
| m_toolbar->setFrameHandle(&m_localFrame); |
| m_functionGraph->setFrameHandle(&m_localFrame); |
| m_numericalColumns->setFrameHandle(&m_localFrame); |
| |
| |
| |
| |
| QVBoxLayout *leftLayout = new QVBoxLayout(); |
| leftLayout->setMargin(0); |
| leftLayout->setSpacing(0); |
| { |
| leftLayout->addWidget(m_toolbar); |
| leftLayout->addSpacing(36); |
| leftLayout->addWidget(m_numericalColumns); |
| } |
| leftPanel->setLayout(leftLayout); |
| |
| addWidget(leftPanel); |
| |
| QVBoxLayout *rightLayout = new QVBoxLayout(); |
| rightLayout->setMargin(0); |
| rightLayout->setSpacing(5); |
| { |
| rightLayout->addWidget(m_segmentViewer, 0); |
| rightLayout->addWidget(m_treeView, 1); |
| } |
| rightPanel->setLayout(rightLayout); |
| |
| addWidget(rightPanel); |
| |
| |
| setSizes(QList<int>() << 500 << 200); |
| setStretchFactor(0, 5); |
| setStretchFactor(1, 2); |
| |
| |
| bool ret = true; |
| ret = ret && connect(m_toolbar, SIGNAL(numericalColumnToggled()), this, SLOT(toggleMode())); |
| ret = ret && connect(ftModel, SIGNAL(activeChannelsChanged()), m_functionGraph, SLOT(update())); |
| ret = ret && connect(ftModel, SIGNAL(activeChannelsChanged()), m_numericalColumns, SLOT(updateAll())); |
| ret = ret && connect(ftModel, SIGNAL(curveChanged(bool)), m_treeView, SLOT(update())); |
| ret = ret && connect(ftModel, SIGNAL(curveChanged(bool)), m_functionGraph, SLOT(update())); |
| ret = ret && connect(ftModel, SIGNAL(curveChanged(bool)), m_numericalColumns, SLOT(updateAll())); |
| ret = ret && connect(ftModel, SIGNAL(curveSelected(TDoubleParam *)), this, SLOT(onCurveSelected(TDoubleParam *))); |
| ret = ret && connect(ftModel, SIGNAL(curveChanged(bool)), m_segmentViewer, SLOT(onCurveChanged())); |
| ret = ret && connect(ftModel, SIGNAL(curveChanged(bool)), this, SLOT(onCurveChanged(bool))); |
| ret = ret && connect(&m_localFrame, SIGNAL(frameSwitched()), this, SLOT(onFrameSwitched())); |
| ret = ret && connect(getSelection(), SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged())); |
| ret = ret && connect(m_functionGraph, SIGNAL(keyframeSelected(double)), m_toolbar, SLOT(setFrame(double))); |
| |
| ret = ret && connect(m_treeView, SIGNAL(switchCurrentObject(TStageObject *)), |
| this, SLOT(doSwitchCurrentObject(TStageObject *))); |
| ret = ret && connect(m_treeView, SIGNAL(switchCurrentFx(TFx *)), |
| this, SLOT(doSwitchCurrentFx(TFx *))); |
| |
| ret = ret && connect(ftModel, SIGNAL(currentChannelChanged(FunctionTreeModel::Channel *)), m_numericalColumns, SLOT(onCurrentChannelChanged(FunctionTreeModel::Channel *))); |
| |
| assert(ret); |
| |
| m_functionGraph->hide(); |
| } |
| |
| |
| |
| FunctionViewer::~FunctionViewer() |
| { |
| delete m_selection; |
| m_toolbar->setFrameHandle(0); |
| } |
| |
| |
| |
| void FunctionViewer::showEvent(QShowEvent *) |
| { |
| refreshModel(); |
| |
| |
| bool ret = true; |
| |
| if (m_xshHandle) { |
| ret = connect(m_xshHandle, SIGNAL(xsheetChanged()), this, SLOT(refreshModel())) && ret; |
| ret = connect(m_xshHandle, SIGNAL(xsheetSwitched()), this, SLOT(rebuildModel())) && ret; |
| } |
| |
| if (m_frameHandle) |
| ret = connect(m_frameHandle, SIGNAL(frameSwitched()), this, SLOT(propagateExternalSetFrame())) && ret; |
| |
| if (m_objectHandle) { |
| ret = connect(m_objectHandle, SIGNAL(objectSwitched()), this, SLOT(onStageObjectSwitched())) && ret; |
| ret = connect(m_objectHandle, SIGNAL(objectChanged(bool)), this, SLOT(onStageObjectChanged(bool))) && ret; |
| } |
| |
| if (m_fxHandle) |
| ret = connect(m_fxHandle, SIGNAL(fxSwitched()), this, SLOT(onFxSwitched())) && ret; |
| |
| |
| if (m_sceneHandle) |
| ret = connect(m_sceneHandle, SIGNAL(sceneSwitched()), m_treeView, SLOT(displayAnimatedChannels())) && ret; |
| |
| assert(ret); |
| |
| m_treeView->setExpanded(m_treeView->model()->index(0, 0), true); |
| m_treeView->setExpanded(m_treeView->model()->index(1, 0), true); |
| |
| FunctionTreeModel *ftm = static_cast<FunctionTreeModel *>(m_treeView->model()); |
| |
| if (m_objectHandle) { |
| assert(m_xshHandle); |
| TXsheet *xsh = m_xshHandle->getXsheet(); |
| |
| const TStageObjectId &objId = m_objectHandle->getObjectId(); |
| ftm->setCurrentStageObject((objId == TStageObjectId::NoneId) ? (TStageObject *)0 : xsh->getStageObject(objId)); |
| } |
| |
| if (m_fxHandle) |
| ftm->setCurrentFx(m_fxHandle->getFx()); |
| } |
| |
| |
| |
| void FunctionViewer::hideEvent(QHideEvent *) |
| { |
| if (m_xshHandle) |
| m_xshHandle->disconnect(this); |
| if (m_frameHandle) |
| m_frameHandle->disconnect(this); |
| if (m_objectHandle) |
| m_objectHandle->disconnect(this); |
| if (m_fxHandle) |
| m_fxHandle->disconnect(this); |
| if (m_sceneHandle) |
| m_sceneHandle->disconnect(this); |
| |
| if (m_functionGraph->isVisible()) |
| m_functionGraph->hide(); |
| } |
| |
| |
| |
| void FunctionViewer::openContextMenu(TreeModel::Item *item, const QPoint &globalPos) |
| { |
| m_treeView->openContextMenu(item, globalPos); |
| } |
| |
| |
| |
| void FunctionViewer::rebuildModel() |
| { |
| getSelection()->selectNone(); |
| onCurveSelected(0); |
| m_functionGraph->getModel()->resetAll(); |
| refreshModel(); |
| m_treeView->displayAnimatedChannels(); |
| } |
| |
| |
| |
| void FunctionViewer::refreshModel() |
| { |
| TXsheet *xsh = m_xshHandle ? m_xshHandle->getXsheet() : 0; |
| |
| m_functionGraph->getModel()->refreshData(xsh); |
| |
| if (xsh) { |
| int rowCount = xsh->getFrameCount(); |
| m_numericalColumns->setRowCount(rowCount); |
| m_numericalColumns->updateAll(); |
| |
| ToonzScene *scene = xsh->getScene(); |
| if (!scene) |
| return; |
| |
| TFilePath scenePath = scene->getScenePath().getParentDir(); |
| if (scene->isUntitled()) |
| scenePath = TProjectManager::instance()->getCurrentProject()->getScenesPath(); |
| |
| m_treeView->setCurrentScenePath(scenePath); |
| |
| int distance, offset; |
| scene->getProperties()->getMarkers(distance, offset); |
| m_numericalColumns->setMarkRow(distance, offset); |
| } |
| |
| m_treeView->updateAll(); |
| m_toolbar->setCurve(0); |
| } |
| |
| |
| |
| void FunctionViewer::setXsheetHandle(TXsheetHandle *xshHandle) |
| { |
| if (xshHandle == m_xshHandle) |
| return; |
| |
| if (m_xshHandle) |
| m_xshHandle->disconnect(this); |
| |
| m_xshHandle = xshHandle; |
| m_segmentViewer->setXsheetHandle(xshHandle); |
| |
| if (m_xshHandle && isVisible()) { |
| TXsheet *xsh = m_xshHandle->getXsheet(); |
| m_functionGraph->getModel()->refreshData(xsh); |
| |
| bool ret = connect(m_xshHandle, SIGNAL(xsheetChanged), this, SLOT(refreshModel())); |
| assert(ret); |
| } |
| } |
| |
| |
| |
| void FunctionViewer::setFrameHandle(TFrameHandle *frameHandle) |
| { |
| if (m_frameHandle == frameHandle) |
| return; |
| |
| if (m_frameHandle) |
| m_frameHandle->disconnect(this); |
| |
| m_frameHandle = frameHandle; |
| |
| if (m_frameHandle && isVisible()) { |
| bool ret = connect(m_frameHandle, SIGNAL(frameSwitched()), this, SLOT(propagateExternalSetFrame())); |
| assert(ret); |
| } |
| } |
| |
| |
| |
| void FunctionViewer::setObjectHandle(TObjectHandle *objectHandle) |
| { |
| if (objectHandle == m_objectHandle) |
| return; |
| |
| if (m_objectHandle) |
| m_objectHandle->disconnect(this); |
| |
| m_objectHandle = objectHandle; |
| |
| if (m_objectHandle && isVisible()) { |
| m_treeView->updateAll(); |
| |
| bool ret = true; |
| ret = connect(m_objectHandle, SIGNAL(objectSwitched()), this, SLOT(onStageObjectSwitched())) && ret; |
| ret = connect(m_objectHandle, SIGNAL(objectChanged(bool)), this, SLOT(onStageObjectChanged(bool))) && ret; |
| |
| assert(ret); |
| } |
| |
| FunctionTreeModel *ftModel = static_cast<FunctionTreeModel *>(m_treeView->model()); |
| if (ftModel) |
| ftModel->setObjectHandle(objectHandle); |
| } |
| |
| |
| void FunctionViewer::setFxHandle(TFxHandle *fxHandle) |
| { |
| if (fxHandle == m_fxHandle) |
| return; |
| |
| if (m_fxHandle) |
| m_fxHandle->disconnect(this); |
| |
| m_fxHandle = fxHandle; |
| |
| if (isVisible()) { |
| m_treeView->updateAll(); |
| |
| bool ret = connect(m_fxHandle, SIGNAL(fxSwitched()), this, SLOT(onFxSwitched())); |
| assert(ret); |
| } |
| |
| FunctionTreeModel *ftModel = static_cast<FunctionTreeModel *>(m_treeView->model()); |
| if (ftModel) |
| ftModel->setFxHandle(fxHandle); |
| } |
| |
| |
| |
| void FunctionViewer::setColumnHandle(TColumnHandle *columnHandle) |
| { |
| if (columnHandle == m_columnHandle) |
| return; |
| |
| m_columnHandle = columnHandle; |
| |
| if (isVisible()) |
| m_treeView->updateAll(); |
| } |
| |
| |
| |
| void FunctionViewer::onFrameSwitched() |
| { |
| int frame = m_localFrame.getFrame(); |
| m_segmentViewer->setSegmentByFrame(m_curve, frame); |
| |
| if (m_frameHandle) |
| m_frameHandle->setFrame(frame); |
| } |
| |
| |
| |
| void FunctionViewer::toggleMode() |
| { |
| if (isHidden()) |
| return; |
| |
| if (m_functionGraph->isVisible()) |
| m_functionGraph->hide(); |
| else |
| m_functionGraph->show(); |
| } |
| |
| |
| |
| void FunctionViewer::onCurveChanged(bool isDragging) |
| { |
| if (m_objectHandle) |
| m_objectHandle->notifyObjectIdChanged(isDragging); |
| |
| |
| if (m_fxHandle) { |
| FunctionTreeModel *ftModel = |
| dynamic_cast<FunctionTreeModel *>(m_treeView->model()); |
| if (ftModel) { |
| FunctionTreeModel::Channel *currChan = ftModel->getCurrentChannel(); |
| if (currChan) { |
| |
| FxChannelGroup *fxChanGroup = |
| dynamic_cast<FxChannelGroup *>(currChan->getChannelGroup()); |
| if (fxChanGroup) |
| m_fxHandle->notifyFxChanged(); |
| } |
| } |
| } |
| } |
| |
| |
| |
| void FunctionViewer::onCurveSelected(TDoubleParam *curve) |
| { |
| m_curve = curve; |
| m_toolbar->setCurve(curve); |
| |
| QPair<TDoubleParam *, int> selectedSegment = getSelection()->getSelectedSegment(); |
| if (selectedSegment.first) |
| m_segmentViewer->setSegment(selectedSegment.first, selectedSegment.second); |
| else |
| m_segmentViewer->setSegment(m_curve, -1); |
| } |
| |
| |
| |
| void FunctionViewer::onValueFieldChanged() |
| { |
| } |
| |
| |
| |
| void FunctionViewer::onXsheetChanged() |
| { |
| TXsheet *xsh = m_xshHandle->getXsheet(); |
| int rowCount = xsh->getFrameCount(); |
| m_numericalColumns->setRowCount(rowCount); |
| } |
| |
| |
| |
| void FunctionViewer::onStageObjectSwitched() |
| { |
| TXsheet *xsh = m_xshHandle->getXsheet(); |
| |
| const TStageObjectId &objId = m_objectHandle->getObjectId(); |
| TStageObject *obj = (objId == TStageObjectId::NoneId) ? (TStageObject *)0 : xsh->getStageObject(objId); |
| |
| static_cast<FunctionTreeModel *>(m_treeView->model())->setCurrentStageObject(obj); |
| |
| m_treeView->updateAll(); |
| m_functionGraph->update(); |
| } |
| |
| |
| |
| void FunctionViewer::onStageObjectChanged(bool isDragging) |
| { |
| TXsheet *xsh = m_xshHandle->getXsheet(); |
| |
| const TStageObjectId &objId = m_objectHandle->getObjectId(); |
| TStageObject *obj = (objId == TStageObjectId::NoneId) ? (TStageObject *)0 : xsh->getStageObject(objId); |
| |
| static_cast<FunctionTreeModel *>(m_treeView->model())->setCurrentStageObject(obj); |
| |
| if (!isDragging) |
| m_treeView->updateAll(); |
| |
| m_functionGraph->update(); |
| } |
| |
| |
| |
| void FunctionViewer::onFxSwitched() |
| { |
| TFx *fx = m_fxHandle->getFx(); |
| TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(fx); |
| if (zfx) |
| fx = zfx->getZeraryFx(); |
| static_cast<FunctionTreeModel *>(m_treeView->model())->setCurrentFx(fx); |
| m_treeView->updateAll(); |
| m_functionGraph->update(); |
| } |
| |
| |
| |
| void FunctionViewer::onSelectionChanged() |
| { |
| QPair<TDoubleParam *, int> selectedSegment = getSelection()->getSelectedSegment(); |
| if (selectedSegment.first) { |
| if (selectedSegment.first != m_curve) { |
| m_curve = selectedSegment.first; |
| m_toolbar->setCurve(selectedSegment.first); |
| } |
| m_segmentViewer->setSegment(selectedSegment.first, selectedSegment.second); |
| } else { |
| m_segmentViewer->setSegment(m_curve, -1); |
| } |
| |
| if (m_functionGraph->isVisible() && !m_functionGraph->hasFocus()) |
| m_functionGraph->update(); |
| } |
| |
| |
| |
| void FunctionViewer::doSwitchCurrentObject(TStageObject *obj) |
| { |
| TStageObjectId id = obj->getId(); |
| if (id.isColumn()) |
| m_columnHandle->setColumnIndex(id.getIndex()); |
| else |
| m_objectHandle->setObjectId(id); |
| } |
| |
| |
| |
| void FunctionViewer::doSwitchCurrentFx(TFx *fx) |
| { |
| if (!fx) { |
| m_fxHandle->setFx(0); |
| return; |
| } |
| if (fx->isZerary()) { |
| TXsheet *xsh = m_xshHandle->getXsheet(); |
| int i, columnCount = xsh->getColumnCount(); |
| for (i = 0; i < columnCount; i++) { |
| TXshColumn *column = xsh->getColumn(i); |
| TXshZeraryFxColumn *zfx = dynamic_cast<TXshZeraryFxColumn *>(xsh->getColumn(i)); |
| if (!zfx) |
| continue; |
| if (zfx->getZeraryColumnFx()->getZeraryFx() == fx) { |
| fx = zfx->getZeraryColumnFx(); |
| m_columnHandle->setColumnIndex(i); |
| break; |
| } |
| } |
| } |
| |
| |
| SwatchViewer::suspendRendering(true, false); |
| |
| int columnIndex = fx->getReferenceColumnIndex(); |
| if (columnIndex >= 0) |
| m_columnHandle->setColumnIndex(columnIndex); |
| |
| SwatchViewer::suspendRendering(false); |
| m_fxHandle->setFx(fx); |
| emit editObject(); |
| } |
| |
| |
| |
| void FunctionViewer::propagateExternalSetFrame() |
| { |
| assert(m_frameHandle); |
| m_localFrame.setFrame(m_frameHandle->getFrame()); |
| } |
| |
| |
| |
| void FunctionViewer::addParameter( |
| TParam *parameter, const TFilePath &folder) |
| { |
| static_cast<FunctionTreeModel *>(m_treeView->model())->addParameter(parameter, folder); |
| } |
| |
| |
| |
| void FunctionViewer::setFocusColumnsOrGraph() |
| { |
| m_numericalColumns->setFocus(); |
| } |
| |
| |
| |
| void FunctionViewer::clearFocusColumnsAndGraph() |
| { |
| m_functionGraph->clearFocus(); |
| m_numericalColumns->clearFocus(); |
| } |
| |
| |
| |
| bool FunctionViewer::columnsOrGraphHasFocus() |
| { |
| return m_functionGraph->hasFocus() || m_numericalColumns->anyWidgetHasFocus() || m_toolbar->anyWidgetHasFocus() || m_segmentViewer->anyWidgetHasFocus(); |
| } |
| |
| |
| |
| void FunctionViewer::setSceneHandle(TSceneHandle *sceneHandle) |
| { |
| m_sceneHandle = sceneHandle; |
| } |
| |
| |
| |
| bool FunctionViewer::isExpressionPageActive() |
| { |
| return m_segmentViewer->isExpressionPageActive(); |
| } |
| |