summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@qt.io>2018-05-22 13:16:47 +0300
committerMiikka Heikkinen <miikka.heikkinen@qt.io>2018-05-23 08:25:48 +0000
commita861b8b1e9a50d4b8d70301cec3a769697389f27 (patch)
tree269a45afcdc79dc5556b203227d1663c5b3a616c
parent5b820599c15c519e14ad697797a5acc0ac792e37 (diff)
Make slide change and property change handling asynchronous
Slide change is an expensive operation that is often accompanied by multitude of property changes, which don't need to be processed, because we are already doing a full reset of the timeline. Changed slide change and property change handling to be done asynchronously. This enables us to ignore duplicate processing, leading to vastly improved slide change times. Task-number: QT3DS-1723 Change-Id: I611c66d42384b894d9a36a3d752c8fb139d50225 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
-rw-r--r--src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp26
-rw-r--r--src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.h1
-rw-r--r--src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineWidget.cpp177
-rw-r--r--src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineWidget.h10
-rw-r--r--src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp5
-rw-r--r--src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTree.cpp25
6 files changed, 170 insertions, 74 deletions
diff --git a/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp b/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp
index 660b7f56..7bd01ff6 100644
--- a/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp
+++ b/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp
@@ -306,7 +306,7 @@ void TimelineGraphicsScene::resetMouseCursor()
void TimelineGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
- if (event->button() == Qt::LeftButton) {
+ if (!m_widgetTimeline->isFullReconstructPending() && event->button() == Qt::LeftButton) {
m_releaseSelectRow = nullptr;
m_dragging = false;
m_startRowMoverOnNextDrag = false;
@@ -504,6 +504,19 @@ TExpandMap &TimelineGraphicsScene::expandMap()
return m_expandMap;
}
+void TimelineGraphicsScene::resetMousePressParams()
+{
+ m_selectionRect->end();
+ m_rowMover->end();
+ m_dragging = false;
+ m_startRowMoverOnNextDrag = false;
+ m_rulerPressed = false;
+ m_keyframePressed = false;
+ m_clickedTimelineControlType = TimelineControlType::None;
+ m_editedTimelineRow = nullptr;
+ m_releaseSelectRow = nullptr;
+}
+
void TimelineGraphicsScene::snap(double &value, bool snapToPlayHead)
{
// snap to play head
@@ -575,16 +588,7 @@ void TimelineGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
m_rowManager->selectRow(m_releaseSelectRow);
}
- // reset mouse press params
- m_selectionRect->end();
- m_rowMover->end();
- m_dragging = false;
- m_startRowMoverOnNextDrag = false;
- m_rulerPressed = false;
- m_keyframePressed = false;
- m_clickedTimelineControlType = TimelineControlType::None;
- m_editedTimelineRow = nullptr;
- m_releaseSelectRow = nullptr;
+ resetMousePressParams();
}
QGraphicsScene::mouseReleaseEvent(event);
diff --git a/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.h b/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.h
index 6033f340..51c0e293 100644
--- a/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.h
+++ b/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.h
@@ -81,6 +81,7 @@ public:
void resetMouseCursor();
void updateSnapSteps();
TExpandMap &expandMap();
+ void resetMousePressParams();
protected:
bool event(QEvent *event) override;
diff --git a/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineWidget.cpp b/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineWidget.cpp
index eeaef985..e9551c10 100644
--- a/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineWidget.cpp
+++ b/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineWidget.cpp
@@ -262,11 +262,10 @@ TimelineWidget::TimelineWidget(const QSize &preferredSize, QWidget *parent)
connect(m_toolbar, &TimelineToolbar::newLayerTriggered, this, [this]() {
using namespace Q3DStudio;
CDoc *doc = g_StudioApp.GetCore()->GetDoc();
- CClientDataModelBridge *bridge = doc->GetStudioSystem()->GetClientDataModelBridge();
// If active instance is component, just bail as we can't add layers to components
qt3dsdm::Qt3DSDMInstanceHandle rootInstance = doc->GetActiveRootInstance();
- if (bridge->GetObjectType(rootInstance) == OBJTYPE_COMPONENT)
+ if (m_bridge->GetObjectType(rootInstance) == OBJTYPE_COMPONENT)
return;
qt3dsdm::Qt3DSDMSlideHandle slide = doc->GetActiveSlide();
@@ -319,6 +318,10 @@ TimelineWidget::TimelineWidget(const QSize &preferredSize, QWidget *parent)
// data model listeners
g_StudioApp.GetCore()->GetDispatch()->AddPresentationChangeListener(this);
g_StudioApp.GetCore()->GetDispatch()->AddClientPlayChangeListener(this);
+
+ m_asyncUpdateTimer.setInterval(0);
+ m_asyncUpdateTimer.setSingleShot(true);
+ connect(&m_asyncUpdateTimer, &QTimer::timeout, this, &TimelineWidget::onAsyncUpdate);
}
Q3DStudio::CString TimelineWidget::getPlaybackMode()
@@ -351,8 +354,10 @@ QSize TimelineWidget::sizeHint() const
void TimelineWidget::OnNewPresentation()
{
// Register callbacks
- qt3dsdm::IStudioFullSystemSignalProvider *theSignalProvider =
- g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetFullSystemSignalProvider();
+ auto studioSystem = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem();
+ qt3dsdm::IStudioFullSystemSignalProvider *theSignalProvider
+ = studioSystem->GetFullSystemSignalProvider();
+ m_bridge = studioSystem->GetClientDataModelBridge();
m_connections.push_back(theSignalProvider->ConnectActiveSlide(
std::bind(&TimelineWidget::onActiveSlide, this, std::placeholders::_1,
@@ -452,41 +457,35 @@ void TimelineWidget::onActiveSlide(const qt3dsdm::Qt3DSDMSlideHandle &inMaster,
if (m_activeSlide == inSlide)
return;
- m_translationManager->Clear();
m_activeSlide = inSlide;
- auto *theSlideSystem = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetSlideSystem();
- auto theSlideInstance = theSlideSystem->GetSlideInstance(inSlide);
-
- m_binding = static_cast<Qt3DSDMTimelineItemBinding *>(
- m_translationManager->GetOrCreate(theSlideInstance));
-
- m_graphicsScene->rowManager()->recreateRowsFromBinding(m_binding);
- m_graphicsScene->updateSnapSteps();
- m_handlesMap.clear();
- insertToHandlesMapRecursive(m_binding);
- m_navigationBar->updateNavigationItems(m_translationManager->GetBreadCrumbProvider());
+ if (!m_fullReconstruct) {
+ m_fullReconstruct = true;
+ m_graphicsScene->resetMousePressParams();
+ if (!m_asyncUpdateTimer.isActive())
+ m_asyncUpdateTimer.start();
+ }
}
void TimelineWidget::insertToHandlesMapRecursive(Qt3DSDMTimelineItemBinding *binding)
{
- if (binding->GetObjectType() != OBJTYPE_MATERIAL) {
- insertToHandlesMap(binding);
-
- const QList<ITimelineItemBinding *> children = binding->GetChildren();
- for (auto child : children)
- insertToHandlesMapRecursive(static_cast<Qt3DSDMTimelineItemBinding *>(child));
- }
+ insertToHandlesMap(binding);
+ const QList<ITimelineItemBinding *> children = binding->GetChildren();
+ for (auto child : children)
+ insertToHandlesMapRecursive(static_cast<Qt3DSDMTimelineItemBinding *>(child));
}
void TimelineWidget::insertToHandlesMap(Qt3DSDMTimelineItemBinding *binding)
{
- if (binding->GetObjectType() != OBJTYPE_MATERIAL)
- m_handlesMap.insert(std::make_pair(binding->GetInstance(), binding->getRowTree()));
+ m_handlesMap.insert(binding->GetInstance(), binding->getRowTree());
}
void TimelineWidget::onSelectionChange(Q3DStudio::SSelectedValue inNewSelectable)
{
+ // Full update will set selection anyway
+ if (m_fullReconstruct)
+ return;
+
qt3dsdm::TInstanceHandleList theInstances = inNewSelectable.GetSelectedInstances();
// First deselect all items in UI
@@ -509,15 +508,15 @@ void TimelineWidget::onSelectionChange(Q3DStudio::SSelectedValue inNewSelectable
void TimelineWidget::onAssetCreated(qt3dsdm::Qt3DSDMInstanceHandle inInstance)
{
- CClientDataModelBridge *theDataModelBridge = g_StudioApp.GetCore()->GetDoc()
- ->GetStudioSystem()->GetClientDataModelBridge();
+ if (m_fullReconstruct)
+ return;
- if (theDataModelBridge->IsSceneGraphInstance(inInstance)) {
+ if (m_bridge->IsSceneGraphInstance(inInstance)) {
Qt3DSDMTimelineItemBinding *binding = getBindingForHandle(inInstance, m_binding);
bool rowExists = binding && binding->getRowTree();
if (binding && !rowExists) {
- Qt3DSDMTimelineItemBinding *bindingParent = getBindingForHandle(theDataModelBridge
+ Qt3DSDMTimelineItemBinding *bindingParent = getBindingForHandle(m_bridge
->GetParentInstance(inInstance), m_binding);
m_graphicsScene->rowManager()
->createRowFromBinding(binding, bindingParent->getRowTree());
@@ -528,11 +527,14 @@ void TimelineWidget::onAssetCreated(qt3dsdm::Qt3DSDMInstanceHandle inInstance)
void TimelineWidget::onAssetDeleted(qt3dsdm::Qt3DSDMInstanceHandle inInstance)
{
- THandleMap::const_iterator it = m_handlesMap.find(inInstance);
+ if (m_fullReconstruct)
+ return;
+
+ RowTree *row = m_handlesMap.value(inInstance);
- if (it != m_handlesMap.end()) { // scene object exists
- m_graphicsScene->rowManager()->deleteRow(it->second);
- m_handlesMap.erase(it);
+ if (row) { // scene object exists
+ m_graphicsScene->rowManager()->deleteRow(row);
+ m_handlesMap.remove(inInstance);
m_graphicsScene->expandMap().remove(inInstance);
}
}
@@ -540,6 +542,9 @@ void TimelineWidget::onAssetDeleted(qt3dsdm::Qt3DSDMInstanceHandle inInstance)
void TimelineWidget::onAnimationCreated(qt3dsdm::Qt3DSDMInstanceHandle parentInstance,
qt3dsdm::Qt3DSDMPropertyHandle property)
{
+ if (m_fullReconstruct)
+ return;
+
Qt3DSDMTimelineItemBinding *binding = getBindingForHandle(parentInstance, m_binding);
if (binding) {
ITimelineItemProperty *propBinding = binding->GetPropertyBinding(property);
@@ -576,6 +581,9 @@ void TimelineWidget::onAnimationCreated(qt3dsdm::Qt3DSDMInstanceHandle parentIns
void TimelineWidget::onAnimationDeleted(qt3dsdm::Qt3DSDMInstanceHandle parentInstance,
qt3dsdm::Qt3DSDMPropertyHandle property)
{
+ if (m_fullReconstruct)
+ return;
+
Qt3DSDMTimelineItemBinding *binding = getBindingForHandle(parentInstance, m_binding);
if (binding) {
ITimelineItemProperty *propBinding = binding->GetPropertyBinding(property);
@@ -593,17 +601,26 @@ void TimelineWidget::onAnimationDeleted(qt3dsdm::Qt3DSDMInstanceHandle parentIns
void TimelineWidget::onKeyframeInserted(qt3dsdm::Qt3DSDMAnimationHandle inAnimation,
qt3dsdm::Qt3DSDMKeyframeHandle inKeyframe)
{
+ if (m_fullReconstruct)
+ return;
+
refreshKeyframe(inAnimation, inKeyframe, ETimelineKeyframeTransaction_Add);
}
void TimelineWidget::onKeyframeDeleted(qt3dsdm::Qt3DSDMAnimationHandle inAnimation,
qt3dsdm::Qt3DSDMKeyframeHandle inKeyframe)
{
+ if (m_fullReconstruct)
+ return;
+
refreshKeyframe(inAnimation, inKeyframe, ETimelineKeyframeTransaction_Delete);
}
void TimelineWidget::onKeyframeUpdated(qt3dsdm::Qt3DSDMKeyframeHandle inKeyframe)
{
+ if (m_fullReconstruct)
+ return;
+
qt3dsdm::IAnimationCore *theAnimationCore =
g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetAnimationCore();
if (theAnimationCore->KeyframeValid(inKeyframe)) {
@@ -636,27 +653,69 @@ void TimelineWidget::refreshKeyframe(qt3dsdm::Qt3DSDMAnimationHandle inAnimation
void TimelineWidget::onPropertyChanged(qt3dsdm::Qt3DSDMInstanceHandle inInstance,
qt3dsdm::Qt3DSDMPropertyHandle inProperty)
{
- CClientDataModelBridge *bridge = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()
- ->GetClientDataModelBridge();
- const SDataModelSceneAsset &asset = bridge->GetSceneAsset();
- const bool filterProperty = inProperty == asset.m_Eyeball || inProperty == asset.m_Locked
- || inProperty == asset.m_Shy;
- const bool timeProperty = inProperty == asset.m_StartTime || inProperty == asset.m_EndTime;
- const bool nameProperty = inProperty == bridge->GetNameProperty();
- if (filterProperty || timeProperty || nameProperty) {
- Qt3DSDMTimelineItemBinding *binding = getBindingForHandle(inInstance, m_binding);
- if (binding) {
- RowTree *row = binding->getRowTree();
- if (row) {
- if (timeProperty)
- row->rowTimeline()->updateDurationFromBinding();
- if (filterProperty)
- row->updateFromBinding();
- if (nameProperty)
- row->updateLabel();
+ if (m_fullReconstruct)
+ return;
+
+ const SDataModelSceneAsset &asset = m_bridge->GetSceneAsset();
+ if (inProperty == asset.m_Eyeball || inProperty == asset.m_Locked || inProperty == asset.m_Shy
+ || inProperty == asset.m_StartTime || inProperty == asset.m_EndTime
+ || inProperty == m_bridge->GetNameProperty()) {
+ m_dirtyProperties.insert(inInstance, inProperty);
+ if (!m_asyncUpdateTimer.isActive())
+ m_asyncUpdateTimer.start();
+ }
+}
+
+void TimelineWidget::onAsyncUpdate()
+{
+ if (m_fullReconstruct) {
+ CDoc *doc = g_StudioApp.GetCore()->GetDoc();
+ m_translationManager->Clear();
+ m_binding = static_cast<Qt3DSDMTimelineItemBinding *>(
+ m_translationManager->GetOrCreate(
+ doc->GetStudioSystem()->GetSlideSystem()->GetSlideInstance(m_activeSlide)));
+ m_graphicsScene->rowManager()->recreateRowsFromBinding(m_binding);
+ m_handlesMap.clear();
+ insertToHandlesMapRecursive(m_binding);
+ m_navigationBar->updateNavigationItems(m_translationManager->GetBreadCrumbProvider());
+ m_graphicsScene->updateSnapSteps();
+ m_fullReconstruct = false;
+ onSelectionChange(doc->GetSelectedValue());
+ } else {
+ // Update properties
+ if (!m_dirtyProperties.isEmpty()) {
+ const SDataModelSceneAsset &asset = m_bridge->GetSceneAsset();
+ qt3dsdm::Qt3DSDMPropertyHandle nameProp = m_bridge->GetNameProperty();
+ for (int instance : qAsConst(m_dirtyProperties)) {
+ bool filterProperty = false;
+ bool timeProperty = false;
+ bool nameProperty = false;
+ const auto props = m_dirtyProperties.values(instance);
+ for (auto prop : props) {
+ filterProperty = filterProperty || prop == asset.m_Eyeball
+ || prop == asset.m_Locked || prop == asset.m_Shy;
+ timeProperty = timeProperty
+ || prop == asset.m_StartTime || prop == asset.m_EndTime;
+ nameProperty = nameProperty || prop == nameProp;
+ }
+ if (filterProperty || timeProperty || nameProperty) {
+ Qt3DSDMTimelineItemBinding *binding = getBindingForHandle(instance, m_binding);
+ if (binding) {
+ RowTree *row = binding->getRowTree();
+ if (row) {
+ if (timeProperty)
+ row->rowTimeline()->updateDurationFromBinding();
+ if (filterProperty)
+ row->updateFromBinding();
+ if (nameProperty)
+ row->updateLabel();
+ }
+ }
+ }
}
}
}
+ m_dirtyProperties.clear();
}
void TimelineWidget::onActionEvent(qt3dsdm::Qt3DSDMActionHandle inAction,
@@ -673,6 +732,9 @@ void TimelineWidget::onActionEvent(qt3dsdm::Qt3DSDMActionHandle inAction,
void TimelineWidget::onPropertyLinked(qt3dsdm::Qt3DSDMInstanceHandle inInstance,
qt3dsdm::Qt3DSDMPropertyHandle inProperty)
{
+ if (m_fullReconstruct)
+ return;
+
Qt3DSDMTimelineItemBinding *binding = getBindingForHandle(inInstance, m_binding);
if (binding) {
@@ -712,6 +774,9 @@ void TimelineWidget::onPropertyUnlinked(qt3dsdm::Qt3DSDMInstanceHandle inInstanc
void TimelineWidget::onChildAdded(int inParent, int inChild, long inIndex)
{
+ if (m_fullReconstruct)
+ return;
+
Qt3DSDMTimelineItemBinding *binding = getBindingForHandle(inChild, m_binding);
Qt3DSDMTimelineItemBinding *bindingParent = getBindingForHandle(inParent, m_binding);
@@ -726,9 +791,7 @@ void TimelineWidget::onChildAdded(int inParent, int inChild, long inIndex)
} else if (rowParent && !row) {
// Parent exists but row not, so create new row.
// (This happens e.g. when deleting a row -> undo)
- CClientDataModelBridge *theDataModelBridge = g_StudioApp.GetCore()->GetDoc()
- ->GetStudioSystem()->GetClientDataModelBridge();
- if (theDataModelBridge->IsSceneGraphInstance(inChild)) {
+ if (m_bridge->IsSceneGraphInstance(inChild)) {
m_graphicsScene->rowManager()
->createRowFromBinding(binding, rowParent, convertedIndex);
insertToHandlesMap(binding);
@@ -748,6 +811,9 @@ void TimelineWidget::onChildRemoved(int inParent, int inChild, long inIndex)
void TimelineWidget::onChildMoved(int inParent, int inChild, long inOldIndex,
long inNewIndex)
{
+ if (m_fullReconstruct)
+ return;
+
Q_UNUSED(inOldIndex)
Qt3DSDMTimelineItemBinding *binding = getBindingForHandle(inChild, m_binding);
@@ -842,7 +908,8 @@ void TimelineWidget::enableDnD(bool b)
if (!b) { // object successfully dropped on the timeline tree
if (m_graphicsScene->rowMover()->insertionParent()
- && !m_graphicsScene->rowMover()->insertionParent()->expanded()) {
+ && !m_graphicsScene->rowMover()->insertionParent()->expanded()
+ && !m_fullReconstruct) {
RowTree *insertionParent = m_graphicsScene->rowMover()->insertionParent();
QTimer::singleShot(0, this, [=]() {
insertionParent->updateExpandStatus(RowTree::ExpandState::Expanded, false);
diff --git a/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineWidget.h b/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineWidget.h
index 75553491..280828ce 100644
--- a/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineWidget.h
+++ b/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineWidget.h
@@ -30,6 +30,7 @@
#define TIMELINEWIDGET_H
#include <QtWidgets/qwidget.h>
+#include <QtCore/qtimer.h>
#include "DispatchListeners.h"
#include "ObjectListModel.h"
#include "Qt3DSDMHandles.h"
@@ -47,6 +48,7 @@ class TimelineSplitter;
class TimelineGraphicsScene;
class CTimelineTranslationManager;
class Qt3DSDMTimelineItemBinding;
+class CClientDataModelBridge;
QT_FORWARD_DECLARE_CLASS(QMouseEvent)
QT_FORWARD_DECLARE_CLASS(QGraphicsView)
@@ -93,6 +95,7 @@ public:
void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
CPt GetPreferredSize() override;
void SetSize(long inX, long inY) override;
+ bool isFullReconstructPending() const { return m_fullReconstruct; }
protected:
// DataModel callbacks
@@ -120,13 +123,14 @@ protected:
void onChildMoved(int inParent, int inChild, long inOldIndex, long inNewIndex);
void onPropertyChanged(qt3dsdm::Qt3DSDMInstanceHandle inInstance,
qt3dsdm::Qt3DSDMPropertyHandle inProperty);
+ void onAsyncUpdate();
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
private:
- typedef std::map<qt3dsdm::Qt3DSDMInstanceHandle, RowTree *> THandleMap;
+ typedef QHash<qt3dsdm::Qt3DSDMInstanceHandle, RowTree *> THandleMap;
Qt3DSDMTimelineItemBinding *getBindingForHandle(int handle,
Qt3DSDMTimelineItemBinding *binding) const;
@@ -147,6 +151,10 @@ private:
Qt3DSDMTimelineItemBinding *m_binding = nullptr;
bool m_splitterPressed = false;
QSize m_preferredSize;
+ QMultiHash<qt3dsdm::Qt3DSDMInstanceHandle, qt3dsdm::Qt3DSDMPropertyHandle> m_dirtyProperties;
+ QTimer m_asyncUpdateTimer;
+ bool m_fullReconstruct = false;
+ CClientDataModelBridge *m_bridge = nullptr;
// data model connection
std::vector<std::shared_ptr<qt3dsdm::ISignalConnection>> m_connections;
diff --git a/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp b/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp
index bf710b22..419759ca 100644
--- a/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp
+++ b/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp
@@ -157,6 +157,11 @@ void RowTimeline::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio
const int keyFrameH = 16;
const int keyFrameY = (TimelineConstants::ROW_H / 2) - (keyFrameH / 2);
+ // Don't access binding when we are in inconsistent state
+ // TODO: Refactor so we don't need to access binding during paint
+ if (m_rowTree->m_scene->widgetTimeline()->isFullReconstructPending())
+ return;
+
if (m_rowTree->hasPropertyChildren()) { // master keyframes
static const QPixmap pixKeyframeMasterNormal
= QPixmap(":/images/Keyframe-Master-Normal.png");
diff --git a/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTree.cpp b/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTree.cpp
index 8434c09d..97df3a09 100644
--- a/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTree.cpp
+++ b/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTree.cpp
@@ -58,6 +58,7 @@ RowTree::RowTree(TimelineGraphicsScene *timelineScene, EStudioObjectType rowType
RowTree::~RowTree()
{
delete m_rowTimeline; // this will also delete the keyframes
+ m_rowTimeline = nullptr;
}
ITimelineItemBinding *RowTree::getBinding() const
@@ -126,13 +127,15 @@ void RowTree::initializeAnimations()
connect(&m_expandAnimation, &QAbstractAnimation::stateChanged,
[this](const QAbstractAnimation::State newState) {
- if (newState == QAbstractAnimation::Running) {
- setVisible(true);
- m_rowTimeline->setVisible(true);
- } else if (newState == QAbstractAnimation::Stopped) {
- if (this->maximumHeight() == 0) {
- setVisible(false);
- m_rowTimeline->setVisible(false);
+ if (m_rowTimeline) {
+ if (newState == QAbstractAnimation::Running) {
+ setVisible(true);
+ m_rowTimeline->setVisible(true);
+ } else if (newState == QAbstractAnimation::Stopped) {
+ if (this->maximumHeight() == 0) {
+ setVisible(false);
+ m_rowTimeline->setVisible(false);
+ }
}
}
});
@@ -315,6 +318,11 @@ void RowTree::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q
static const QPixmap pixCompAction = QPixmap(":/images/Action-ComponentAction.png");
if (!isProperty()) {
+ // Don't access binding when we are in inconsistent state
+ // TODO: Refactor so we don't need to access binding during paint
+ if (m_scene->widgetTimeline()->isFullReconstructPending())
+ return;
+
Qt3DSDMTimelineItemBinding *itemBinding =
static_cast<Qt3DSDMTimelineItemBinding *>(m_binding);
if (itemBinding->HasAction(true)) // has master action
@@ -730,6 +738,9 @@ void RowTree::updateExpandStatus(ExpandState state, bool animate)
{
m_expandState = state;
+ if (m_scene->widgetTimeline()->isFullReconstructPending())
+ return;
+
// Store the expanded state of items so we can restore it on slide change
if (m_binding) {
m_scene->expandMap().insert(