diff options
author | Pasi Keränen <pasi.keranen@qt.io> | 2019-06-05 13:22:33 +0300 |
---|---|---|
committer | Pasi Keränen <pasi.keranen@qt.io> | 2019-06-10 21:22:35 +0300 |
commit | fa46a1dc716c499b5eefdfd8f0cfcfc8ac303937 (patch) | |
tree | 61f7f6eed72822cf39a52769dfaba24d1bde9522 /src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowManager.cpp | |
parent | fe7649841f68c6fe99bf08e477df77770c7dffa0 (diff) |
Switch to qt3dstudio/ogl-runtime submodule
Module config change so that ogl-runtime builds from submodule.
Task-number: QT3DS-3600
Change-Id: Ib22fda6aed1cf9336f15b79256b5f9db8774159f
Reviewed-by: Pasi Keränen <pasi.keranen@qt.io>
Diffstat (limited to 'src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowManager.cpp')
-rw-r--r-- | src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowManager.cpp | 414 |
1 files changed, 414 insertions, 0 deletions
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowManager.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowManager.cpp new file mode 100644 index 00000000..50eff996 --- /dev/null +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowManager.cpp @@ -0,0 +1,414 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "RowManager.h" +#include "RowTree.h" +#include "TimelineGraphicsScene.h" +#include "Ruler.h" +#include "TreeHeader.h" +#include "KeyframeManager.h" +#include "Keyframe.h" +#include "StudioObjectTypes.h" +#include "Bindings/ITimelineItemBinding.h" +#include "Bindings/Qt3DSDMTimelineItemBinding.h" +#include "Bindings/ITimelineTimebar.h" +#include "Bindings/Qt3DSDMTimelineKeyframe.h" +#include "StudioApp.h" +#include "Core.h" +#include "Doc.h" +#include "StudioObjectTypes.h" +#include "Qt3DSDMStudioSystem.h" +#include "ClientDataModelBridge.h" + +#include <QtWidgets/qgraphicslinearlayout.h> +#include <QtCore/qpointer.h> +#include <QtCore/qtimer.h> + +RowManager::RowManager(TimelineGraphicsScene *scene, QGraphicsLinearLayout *layoutLabels, + QGraphicsLinearLayout *layoutTimeline) + : m_scene(scene) + , m_layoutTree(layoutLabels) + , m_layoutTimeline(layoutTimeline) +{ + +} + +RowManager::~RowManager() +{ + finalizeRowDeletions(); +} + +void RowManager::recreateRowsFromBinding(ITimelineItemBinding *rootBinding) +{ + removeAllRows(); + createRowsFromBindingRecursive(rootBinding); +} + +void RowManager::removeAllRows() +{ + m_scene->keyframeManager()->deselectAllKeyframes(); + clearSelection(); + + // delete rows + RowTree *row_i; + for (int i = m_layoutTree->count() - 1; i >= 1; --i) { + row_i = static_cast<RowTree *>(m_layoutTree->itemAt(i)->graphicsItem()); + m_layoutTree->removeAt(i); + m_layoutTimeline->removeAt(i); + delete row_i; // this will also delete the timeline row + } +} + +RowTree *RowManager::createRowFromBinding(ITimelineItemBinding *binding, RowTree *parentRow, + int index) +{ + RowTree *newRow = createRow(binding->GetTimelineItem()->GetObjectType(), parentRow, + binding->GetTimelineItem()->GetName().toQString(), + QString(), index); + + // connect the new row and its binding + binding->setRowTree(newRow); + newRow->setBinding(binding); + + // hide if material container + auto bridge = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetClientDataModelBridge(); + if (bridge->isMaterialContainer(newRow->instance())) { + newRow->setVisible(false); + newRow->rowTimeline()->setVisible(false); + } + + // set row start/end time & color + ITimelineTimebar *timebar = binding->GetTimelineItem()->GetTimebar(); + RowTimeline *rowTimeline = newRow->rowTimeline(); + rowTimeline->clearBoundChildren(); + rowTimeline->setStartTime(timebar->GetStartTime()); + rowTimeline->setEndTime(timebar->GetEndTime()); + rowTimeline->setBarColor(timebar->GetTimebarColor()); + + // create property rows + for (int i = 0; i < binding->GetPropertyCount(); i++) { + ITimelineItemProperty *prop_i = binding->GetProperty(i); + RowTree *propRow = getOrCreatePropertyRow(newRow, prop_i->GetName().toQString()); + + // connect the property row and its binding + prop_i->setRowTree(propRow); + propRow->setPropBinding(prop_i); + + // add keyframes + for (int j = 0; j < prop_i->GetKeyframeCount(); j++) { + Qt3DSDMTimelineKeyframe *kf + = static_cast<Qt3DSDMTimelineKeyframe *>(prop_i->GetKeyframeByIndex(j)); + + QList<Keyframe *> addedKeyframes + = m_scene->keyframeManager()->insertKeyframe(propRow->rowTimeline(), + kf->GetTime(), false); + + Keyframe *kfUI = addedKeyframes.at(0); + kf->setUI(kfUI); + kfUI->binding = kf; + kfUI->dynamic = kf->IsDynamic(); + } + } + + updateRulerDuration(); + + return newRow; +} + +void RowManager::createRowsFromBindingRecursive(ITimelineItemBinding *binding, RowTree *parentRow) +{ + auto instance = static_cast<Qt3DSDMTimelineItemBinding *>(binding)->GetInstance(); + + RowTree *newRow = createRowFromBinding(binding, parentRow); + // create child rows recursively + const QList<ITimelineItemBinding *> children = binding->GetChildren(); + for (auto child : children) + createRowsFromBindingRecursive(child, newRow); +} + +RowTree *RowManager::getOrCreatePropertyRow(RowTree *masterRow, const QString &propType, int index) +{ + RowTree *propertyRow = masterRow->getPropertyRow(propType); + if (!propertyRow) + propertyRow = createRow(OBJTYPE_UNKNOWN, masterRow, {}, propType, index); + + propertyRow->updateLock(masterRow->locked()); + + return propertyRow; +} + +RowTree *RowManager::createRow(EStudioObjectType rowType, RowTree *parentRow, const QString &label, + const QString &propType, int index) +{ + if (parentRow && parentRow->isProperty()) { + qWarning() << __FUNCTION__ << "Property row cannot have children. No row added."; + } else { + // If the row doesnt have a parent, insert it under the scene (first row is the tree header) + if (!parentRow && rowType != OBJTYPE_SCENE && m_layoutTree->count() > 1) + parentRow = static_cast<RowTree *>(m_layoutTree->itemAt(1)); + + RowTree *rowTree = nullptr; + + if (!propType.isEmpty()) // property row + rowTree = new RowTree(m_scene, propType); + else + rowTree = new RowTree(m_scene, rowType, label); + + if (parentRow) { + if (index != -1) + parentRow->addChildAt(rowTree, index); + else + parentRow->addChild(rowTree); + } else { + // root element, no parent + m_layoutTree->insertItem(1, rowTree); + m_layoutTimeline->insertItem(1, rowTree->rowTimeline()); + } + + return rowTree; + } + + return nullptr; +} + +RowTree *RowManager::getRowAtPos(const QPointF &scenePos) const +{ + const QList<QGraphicsItem *> items = m_scene->items(scenePos); + + for (auto item : items) { + if (item->type() == TimelineItem::TypeRowTree) + return static_cast<RowTree *>(item); + } + + return nullptr; +} + +// Call this to select/unselect row, affecting bindings +void RowManager::selectRow(RowTree *row, bool multiSelect) +{ + if (!row) { + g_StudioApp.GetCore()->GetDoc()->DeselectAllItems(); + return; + } + + if (row->locked()) + return; + + if (row->isProperty()) + row = row->parentRow(); + + if (multiSelect && m_selectedRows.size() > 0) { + // Do not allow singular object types into multiselection + if ((row->objectType() | m_selectedRows[0]->objectType()) & OBJTYPE_IS_SINGULAR) + return; + } + + Qt3DSDMTimelineItemBinding *binding + = static_cast<Qt3DSDMTimelineItemBinding *>(row->getBinding()); + if (binding) + binding->SetSelected(multiSelect); +} + +// Call this to update row selection UI status +void RowManager::setRowSelection(RowTree *row, bool selected) +{ + if (!row) + return; + + if (selected) { + if (!m_selectedRows.contains(row)) + m_selectedRows.append(row); + row->setState(InteractiveTimelineItem::Selected); + // Expand parents if not expanded + QPointer<RowTree> pRow = row->parentRow(); + if (!pRow.isNull()) { + QTimer::singleShot(0, [this, pRow]() { + if (!pRow.isNull()) + ensureRowExpandedAndVisible(pRow, false); + }); + } + } else { + m_selectedRows.removeAll(row); + row->setState(InteractiveTimelineItem::Normal); + } +} + +// Call this to clear all selections UI status +void RowManager::clearSelection() +{ + for (auto row : qAsConst(m_selectedRows)) + row->setState(InteractiveTimelineItem::Normal); + m_selectedRows.clear(); +} + +// Updates duration of ruler +// When you don't want to update max duration (so width of timeline, scrollbar) +// set updateMaxDuration to false. +void RowManager::updateRulerDuration(bool updateMaxDuration) +{ + long duration = 0; + long maxDuration = 0; // for setting correct size for the view so scrollbars appear correctly + if (m_layoutTree->count() > 1) { + auto rootRow = static_cast<RowTree *>(m_layoutTree->itemAt(1)->graphicsItem()); + bool isComponent = rootRow->objectType() == OBJTYPE_COMPONENT; + for (int i = 1; i < m_layoutTree->count(); ++i) { + RowTree *row_i = static_cast<RowTree *>(m_layoutTree->itemAt(i)->graphicsItem()); + long dur_i = row_i->rowTimeline()->getEndTime(); + + if (((isComponent && i != 1) || row_i->objectType() == OBJTYPE_LAYER) + && dur_i > duration) { + duration = dur_i; + } + + if (dur_i > maxDuration) + maxDuration = dur_i; + } + rootRow->rowTimeline()->setEndTime(duration); + } + + m_scene->ruler()->setDuration(duration); + + if (updateMaxDuration) + m_scene->ruler()->setMaxDuration(maxDuration); +} + +void RowManager::updateFiltering(RowTree *row) +{ + if (!row) // update all rows + row = static_cast<RowTree *>(m_layoutTree->itemAt(1)); + updateRowFilterRecursive(row); +} + +void RowManager::updateRowFilterRecursive(RowTree *row) +{ + row->updateFilter(); + + if (!row->empty()) { + const auto childRows = row->childRows(); + for (auto child : childRows) + updateRowFilterRecursive(child); + row->updateArrowVisibility(); + } +} + +void RowManager::deleteRow(RowTree *row) +{ + if (row && row->objectType() != OBJTYPE_SCENE) { + if (row->parentRow()) + row->parentRow()->removeChild(row); + + deleteRowRecursive(row, true); + } +} + +void RowManager::finalizeRowDeletions() +{ + for (auto row : qAsConst(m_deletedRows)) { + // If the row has been reparented, no need to delete it + if (!row->parentRow()) + deleteRowRecursive(row, false); + } + m_deletedRows.clear(); +} + +void RowManager::deleteRowRecursive(RowTree *row, bool deferChildRows) +{ + if (!row->childProps().empty()) { + const auto childProps = row->childProps(); + for (auto child : childProps) + deleteRowRecursive(child, false); + } + + if (!row->childRows().empty()) { + const auto childRows = row->childRows(); + for (auto child : childRows) { + if (deferChildRows) { + // Let's not delete child rows just yet, there may be a pending move for them. + // This happens when the same transaction contains parent deletion and child row + // move, such as ungrouping items. + child->setParentRow(nullptr); + m_deletedRows.append(child); + } else { + deleteRowRecursive(child, false); + } + } + } + + m_selectedRows.removeAll(row); + m_deletedRows.removeAll(row); // Row actually deleted, remove it from pending deletes + + m_scene->keyframeManager()->deleteKeyframes(row->rowTimeline(), false); + + if (row->getBinding()) + static_cast<Qt3DSDMTimelineItemBinding *>(row->getBinding())->setRowTree(nullptr); + + delete row; +} + +RowTree *RowManager::selectedRow() const +{ + if (m_selectedRows.size() == 1) + return m_selectedRows.first(); + return nullptr; +} + +bool RowManager::isComponentRoot() const +{ + if (m_layoutTree->count() > 1) { + RowTree *root = static_cast<RowTree *>(m_layoutTree->itemAt(1)->graphicsItem()); + return root->objectType() == OBJTYPE_COMPONENT; + } + return false; +} + +bool RowManager::isRowSelected(RowTree *row) const +{ + return m_selectedRows.contains(row); +} + +QVector<RowTree *> RowManager::selectedRows() const +{ + return m_selectedRows; +} + +void RowManager::ensureRowExpandedAndVisible(RowTree *row, bool forceChildUpdate) const +{ + RowTree *parentRow = row; + while (parentRow) { + parentRow->updateExpandStatus(parentRow->expandHidden() + ? RowTree::ExpandState::HiddenExpanded + : RowTree::ExpandState::Expanded, false, + forceChildUpdate); + parentRow = parentRow->parentRow(); + } +} + +bool RowManager::isSingleSelected() const +{ + return m_selectedRows.size() == 1; +} |