From 0c43f1b286d33d9d3c84e0f00ada30a6e18fd3b2 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Tue, 3 Sep 2019 15:01:11 +0300 Subject: Allow moving one or more curves keyframes vertically MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also: - utilize an updatable editor to undo bezier curve editing - allow ctrl+click to deselect a selected keyframe on a curve Task-number: QT3DS-3922 Change-Id: Ie71034431e56fdf47ab12fc20f96455fba2d5314 Reviewed-by: Antti Määttä Reviewed-by: Miikka Heikkinen --- .../Palettes/TimelineGraphicsView/RowTypes.h | 24 +++++--- .../TimelineGraphicsView/TimelineGraphicsScene.cpp | 6 +- .../ui/RowTimelinePropertyGraph.cpp | 69 ++++++++++++++-------- .../ui/RowTimelinePropertyGraph.h | 4 +- 4 files changed, 65 insertions(+), 38 deletions(-) diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowTypes.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowTypes.h index c567c7db..faeeae68 100644 --- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowTypes.h +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowTypes.h @@ -31,17 +31,23 @@ #include -enum class TimelineControlType { - None, - KeyFrame, - Duration, - DurationStartHandle, - DurationEndHandle, - BezierKeyframe, - BezierInHandle, - BezierOutHandle +enum class TimelineControlType : int { + None = 0x00, + KeyFrame = 0x01, + Duration = 0x02, + DurationStartHandle = 0x04, + DurationEndHandle = 0x08, + BezierKeyframe = 0x10, + BezierInHandle = 0x20, + BezierOutHandle = 0x40, + IsBezierControl = BezierKeyframe | BezierInHandle | BezierOutHandle }; +inline int operator &(TimelineControlType lhs, TimelineControlType rhs) +{ + return int(lhs) & int(rhs); +} + enum class TreeControlType { None, Arrow, diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp index b792639f..bae5af8f 100644 --- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp @@ -634,8 +634,7 @@ void TimelineGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) bool shift = event->modifiers() & Qt::ShiftModifier; if (m_dragging) { - if (m_clickedTimelineControlType == TimelineControlType::BezierInHandle - || m_clickedTimelineControlType == TimelineControlType::BezierOutHandle) { + if (m_clickedTimelineControlType & TimelineControlType::IsBezierControl) { if (m_editedTimelineRow && m_editedTimelineRow->propertyGraph()) { m_editedTimelineRow->propertyGraph()->updateBezierControlValue( m_clickedTimelineControlType, event->scenePos()); @@ -846,8 +845,7 @@ void TimelineGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) if (m_playHead->time() > ruler()->duration()) g_StudioApp.GetCore()->GetDoc()->NotifyTimeChanged(ruler()->duration()); } - } else if (m_clickedTimelineControlType == TimelineControlType::BezierInHandle - || m_clickedTimelineControlType == TimelineControlType::BezierOutHandle) { + } else if (m_clickedTimelineControlType & TimelineControlType::IsBezierControl) { if (m_editedTimelineRow->propertyGraph()) m_editedTimelineRow->propertyGraph()->commitBezierEdit(); } diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.cpp index a17ee632..b21b80a6 100644 --- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.cpp +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.cpp @@ -48,6 +48,7 @@ RowTimelinePropertyGraph::RowTimelinePropertyGraph(QObject *parent) : QObject(parent) , m_rowTimeline(static_cast(parent)) , m_animCore(g_StudioApp.GetCore()->GetDoc()->GetAnimationCore()) + , m_UpdatableEditor(*g_StudioApp.GetCore()->GetDoc()) { m_fitCurveTimer.setInterval(10); @@ -215,12 +216,12 @@ TimelineControlType RowTimelinePropertyGraph::getClickedBezierControl(const QPoi // reset data m_hoveredBezierKeyframe = 0; - m_currKeyframeData.first = 0; + m_pressedKeyframeHandle = 0; if (aKeyframeWasHovered) m_rowTimeline->update(); - for (size_t i = 0; i < m_activeChannels.size(); ++i) { + for (int i = 0; i < m_activeChannels.size(); ++i) { Qt3DSDMTimelineKeyframe::TKeyframeHandleList keyframeHandles; m_animCore->GetKeyframes(m_activeChannels[i], keyframeHandles); const double CONTROL_RADIUS = 8; @@ -229,15 +230,20 @@ TimelineControlType RowTimelinePropertyGraph::getClickedBezierControl(const QPoi QPointF kfPos = getBezierControlPosition(kf); if (QLineF(kfPos, pos).length() < CONTROL_RADIUS) { // over a bezier keyframe - m_currKeyframeData.first = kfHandle; - m_currKeyframeData.second = m_animCore->GetKeyframeData(kfHandle); + m_pressedKeyframeHandle = kfHandle; if (isHover) { m_hoveredBezierKeyframe = kfHandle; } else { - if (!CHotKeys::isCtrlDown()) - m_selectedBezierKeyframes.clear(); - - m_selectedBezierKeyframes.insert(kfHandle); + if (CHotKeys::isCtrlDown()) { + if (m_selectedBezierKeyframes.contains(kfHandle)) + m_selectedBezierKeyframes.remove(kfHandle); + else + m_selectedBezierKeyframes.insert(kfHandle); + } else { + if (!m_selectedBezierKeyframes.contains(kfHandle)) + m_selectedBezierKeyframes.clear(); + m_selectedBezierKeyframes.insert(kfHandle); + } } m_rowTimeline->update(); @@ -250,8 +256,7 @@ TimelineControlType RowTimelinePropertyGraph::getClickedBezierControl(const QPoi bool clickedInHandle = QLineF(cInPos, pos).length() < CONTROL_RADIUS; bool clickedOutHandle = QLineF(cOutPos, pos).length() < CONTROL_RADIUS; if (clickedInHandle || clickedOutHandle) { - m_currKeyframeData.first = kfHandle; - m_currKeyframeData.second = m_animCore->GetKeyframeData(kfHandle); + m_pressedKeyframeHandle = kfHandle; return clickedInHandle ? TimelineControlType::BezierInHandle : TimelineControlType::BezierOutHandle; @@ -291,8 +296,8 @@ QPointF RowTimelinePropertyGraph::getKeyframePosition(long time, float value) co } /** - * This method is called when the user drags a bezier handle. It updates the bezier keyframe - * tangent value based on the current position of the handle. + * This method is called when the user drags a bezier control. It updates the bezier control + * values based on the current position of the handle. * * @param controlType which handle is being dragged? (BezierInHandle or BezierOutHandle) * @param scenePos handle position in timeline scene coordinates @@ -307,7 +312,27 @@ void RowTimelinePropertyGraph::updateBezierControlValue(TimelineControlType cont float value = (m_graphY - p.y()) / m_valScale; adjustColorProperty(value, false); - SBezierKeyframe kf = get(m_currKeyframeData.second); + SBezierKeyframe kf = get(m_animCore->GetKeyframeData(m_pressedKeyframeHandle)); + + // moving selected keyframes (vertically) + if (controlType == TimelineControlType::BezierKeyframe) { + float dVal = value - kf.m_value; + + for (auto kfHandle : m_selectedBezierKeyframes) { + SBezierKeyframe kf_i = get(m_animCore->GetKeyframeData(kfHandle)); + kf_i.m_value += dVal; + kf_i.m_InTangentValue += dVal; + kf_i.m_OutTangentValue += dVal; + m_UpdatableEditor.EnsureEditor(QObject::tr("Edit Bezier curve"), __FILE__, __LINE__) + .setBezierKeyframeValue(kfHandle, kf_i); + } + // immediate refresh is needed to update the value in the inspector, this is not needed + // when moving the control points as they are not shown in the inspector + m_UpdatableEditor.FireImmediateRefresh(m_rowTimeline->rowTree()->parentRow()->instance()); + m_rowTimeline->update(); + return; + } + bool isBezierIn = controlType == TimelineControlType::BezierInHandle; // prevent handles from moving to the other side of the keyframe @@ -317,11 +342,11 @@ void RowTimelinePropertyGraph::updateBezierControlValue(TimelineControlType cont } // prevent handles from going beyond prev. and next keyframes - Qt3DSDMAnimationHandle anim = m_animCore->GetAnimationForKeyframe(m_currKeyframeData.first); + Qt3DSDMAnimationHandle anim = m_animCore->GetAnimationForKeyframe(m_pressedKeyframeHandle); Qt3DSDMTimelineKeyframe::TKeyframeHandleList keyframeHandles; m_animCore->GetKeyframes(anim, keyframeHandles); for (size_t i = 0; i < keyframeHandles.size(); ++i) { - if (keyframeHandles[i] == m_currKeyframeData.first) { + if (keyframeHandles[i] == m_pressedKeyframeHandle) { long currKfTime = getKeyframeTime(m_animCore->GetKeyframeData(keyframeHandles[i])); long prevKfTime = i > 0 ? getKeyframeTime(m_animCore->GetKeyframeData(keyframeHandles[i - 1])) @@ -358,7 +383,9 @@ void RowTimelinePropertyGraph::updateBezierControlValue(TimelineControlType cont otherHandleValue = kf.m_value + (kf.m_value - currHandleValue); } - m_animCore->SetKeyframeData(m_currKeyframeData.first, kf); + m_UpdatableEditor.EnsureEditor(QObject::tr("Edit Bezier curve"), __FILE__, __LINE__) + .setBezierKeyframeValue(m_pressedKeyframeHandle, kf); + m_rowTimeline->update(); } void RowTimelinePropertyGraph::updateChannelFiltering(const QVector &activeChannels) @@ -469,7 +496,7 @@ void RowTimelinePropertyGraph::selectBezierKeyframesInRange(const QRectF &rect) void RowTimelinePropertyGraph::deselectAllBezierKeyframes() { - if (!m_currKeyframeData.first.Valid()) // not currently editing a bezier control + if (!m_pressedKeyframeHandle.Valid()) // not currently editing a bezier control m_selectedBezierKeyframes.clear(); } @@ -503,13 +530,7 @@ void RowTimelinePropertyGraph::pan(qreal dy) void RowTimelinePropertyGraph::commitBezierEdit() { - // reset the moved keyframe and commit the change, so the undo/redo works correctly - // Mahmoud_TODO: improve this (using Updatable editor?) - TKeyframe movedKeyframe = m_animCore->GetKeyframeData(m_currKeyframeData.first); - m_animCore->SetKeyframeData(m_currKeyframeData.first, m_currKeyframeData.second); - - Q3DStudio::SCOPED_DOCUMENT_EDITOR(*g_StudioApp.GetCore()->GetDoc(), tr("Edit Bezier curve")) - ->setBezierKeyframeValue(m_currKeyframeData.first, movedKeyframe); + m_UpdatableEditor.CommitEditor(); } void RowTimelinePropertyGraph::setExpandHeight(int h) diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.h index b3ec82b1..7d6bffc8 100644 --- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.h +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.h @@ -33,6 +33,7 @@ #include "RowTypes.h" #include "TimelineConstants.h" #include "Bindings/Qt3DSDMTimelineKeyframe.h" +#include "IDocumentEditor.h" #include #include @@ -75,7 +76,7 @@ private: void checkValScaleLimits(); void adjustColorProperty(float &val, bool scaleUp = true) const; - std::pair m_currKeyframeData; + qt3dsdm::Qt3DSDMKeyframeHandle m_pressedKeyframeHandle; RowTimeline *m_rowTimeline = nullptr; ITimelineItemProperty *m_propBinding = nullptr; qt3dsdm::IAnimationCore *m_animCore = nullptr; @@ -88,6 +89,7 @@ private: QVector m_activeChannels; // active channels anim. handles QVector m_activeChannelsIndex; QTimer m_fitCurveTimer; + Q3DStudio::CUpdateableDocumentEditor m_UpdatableEditor; }; #endif // ROWTIMELINEPROPERTYGRAPH_H -- cgit v1.2.3