summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdDataModelInsertKeyframe.h37
-rw-r--r--src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.cpp7
-rw-r--r--src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.h3
-rw-r--r--src/Authoring/Client/Code/Core/Doc/Doc.cpp8
-rw-r--r--src/Authoring/Client/Code/Core/Doc/Doc.h1
-rw-r--r--src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp43
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IComposerSerializer.cpp2
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h2
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IKeyframesManager.h9
-rw-r--r--src/Authoring/Client/Code/Core/Utility/StudioPreferences.cpp5
-rw-r--r--src/Authoring/Client/Code/Core/Utility/StudioPreferences.h1
-rw-r--r--src/Authoring/Qt3DStudio/Application/StudioApp.cpp1
-rw-r--r--src/Authoring/Qt3DStudio/MainFrm.cpp4
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/ITimelineItemProperty.h11
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/PasteKeyframesCommandHelper.h53
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemProperty.cpp25
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemProperty.h18
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineKeyframe.cpp46
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/Keyframe.h4
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/KeyframeManager.cpp91
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/KeyframeManager.h15
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowTypes.h6
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineConstants.h3
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp99
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.h7
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.cpp6
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp21
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.h1
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelineContextMenu.cpp108
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelineContextMenu.h2
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.cpp369
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.h36
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.cpp89
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.h8
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/TimelineItem.cpp2
-rw-r--r--src/Authoring/Qt3DStudio/UI/InterpolationDlg.cpp25
-rw-r--r--src/Authoring/Qt3DStudio/UI/InterpolationDlg.h23
-rw-r--r--src/Authoring/Qt3DStudio/UI/InterpolationDlg.ui621
-rw-r--r--src/Authoring/Qt3DStudio/Workspace/Dialogs.cpp20
-rw-r--r--src/Authoring/Qt3DStudio/Workspace/Dialogs.h2
m---------src/Runtime/ogl-runtime0
41 files changed, 1185 insertions, 649 deletions
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdDataModelInsertKeyframe.h b/src/Authoring/Client/Code/Core/Commands/CmdDataModelInsertKeyframe.h
index a1182280..f2ea635f 100644
--- a/src/Authoring/Client/Code/Core/Commands/CmdDataModelInsertKeyframe.h
+++ b/src/Authoring/Client/Code/Core/Commands/CmdDataModelInsertKeyframe.h
@@ -28,13 +28,8 @@
****************************************************************************/
#ifndef INCLUDED_CMD_DATAMODEL_INSERTKEYFRAME_H
-#define INCLUDED_CMD_DATAMODEL_INSERTKEYFRAME_H 1
+#define INCLUDED_CMD_DATAMODEL_INSERTKEYFRAME_H
-#pragma once
-
-//==============================================================================
-// Include
-//==============================================================================
#include "Cmd.h"
#include "CmdDataModel.h"
#include "Doc.h"
@@ -51,7 +46,7 @@ public:
struct STimeKeyframeData
{
qt3dsdm::Qt3DSDMPropertyHandle m_Property;
- float m_KeyframeTime;
+ float m_KeyframeTime; // seconds
qt3dsdm::SGetOrSetKeyframeInfo m_Infos[4];
size_t m_ValidInfoCount;
@@ -69,22 +64,15 @@ public:
protected:
typedef std::vector<STimeKeyframeData> TKeyframeDataList;
-protected: // Members
CDoc *m_Doc;
qt3dsdm::Qt3DSDMInstanceHandle m_Instance;
TKeyframeDataList m_KeyframeDataList;
-public: // Construction
- //@param inTime is in secs
- CCmdDataModelInsertKeyframe(CDoc *inDoc, qt3dsdm::Qt3DSDMInstanceHandle inInstance,
- qt3dsdm::Qt3DSDMPropertyHandle inProperty, float inKeyframeTime,
- qt3dsdm::SGetOrSetKeyframeInfo *inInfos, size_t inInfoCount)
+public:
+ CCmdDataModelInsertKeyframe(CDoc *inDoc, qt3dsdm::Qt3DSDMInstanceHandle inInstance)
: qt3dsdm::CmdDataModel(*inDoc)
, m_Doc(inDoc)
- , m_Instance(inInstance)
- {
- AddKeyframeData(inProperty, inKeyframeTime, inInfos, inInfoCount);
- }
+ , m_Instance(inInstance) {}
~CCmdDataModelInsertKeyframe() {}
void AddKeyframeData(qt3dsdm::Qt3DSDMPropertyHandle inProperty, float inTime,
@@ -93,31 +81,25 @@ public: // Construction
m_KeyframeDataList.push_back(STimeKeyframeData(inProperty, inTime, inInfos, inInfoCount));
}
- //======================================================================
- // Do/Redo
- //======================================================================
unsigned long Do() override
{
if (!ConsumerExists()) {
qt3dsdm::SScopedDataModelConsumer __scopedConsumer(*this);
qt3dsdm::IStudioAnimationSystem *theAnimationSystem =
m_Doc->GetStudioSystem()->GetAnimationSystem();
- // if there are existing keyframes exist at the same times, the values are overridden. (
- // That's how it always work in studio anyways )
- for (size_t i = 0; i < m_KeyframeDataList.size(); ++i)
+ // Keyframes at same time are overridden (only 1 keyframe allowed at a point in time)
+ for (size_t i = 0; i < m_KeyframeDataList.size(); ++i) {
theAnimationSystem->SetOrCreateKeyframe(
m_Instance, m_KeyframeDataList[i].m_Property,
m_KeyframeDataList[i].m_KeyframeTime, m_KeyframeDataList[i].m_Infos,
m_KeyframeDataList[i].m_ValidInfoCount);
+ }
} else {
DataModelRedo();
}
return 0;
}
- //======================================================================
- // Undo
- //======================================================================
unsigned long Undo() override
{
if (ConsumerExists()) {
@@ -126,9 +108,6 @@ public: // Construction
return 0;
}
- //======================================================================
- // ToString
- //======================================================================
QString ToString() override
{
return QObject::tr("Insert Keyframe");
diff --git a/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.cpp b/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.cpp
index f6beca04..51256fe5 100644
--- a/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.cpp
+++ b/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.cpp
@@ -288,6 +288,7 @@ qt3dsdm::Qt3DSDMPropertyHandle CClientDataModelBridge::GetImportId()
{
return m_SceneAsset.m_ImportId;
}
+
qt3dsdm::Qt3DSDMPropertyHandle CClientDataModelBridge::GetNameProperty() const
{
return GetObjectDefinitions().m_Named.m_NameProp;
@@ -2246,3 +2247,9 @@ CClientDataModelBridge::GetAggregateInstancePropertyByName(Qt3DSDMInstanceHandle
{
return m_DataCore->GetAggregateInstancePropertyByName(inInstance, inPropertyName);
}
+
+bool CClientDataModelBridge::hasAggregateInstanceProperty(Qt3DSDMInstanceHandle inInstance,
+ Qt3DSDMPropertyHandle inProperty) const
+{
+ return m_DataCore->HasAggregateInstanceProperty(inInstance, inProperty);
+}
diff --git a/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.h b/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.h
index aa7a5dee..10841259 100644
--- a/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.h
+++ b/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.h
@@ -37,6 +37,7 @@
#include "Graph.h"
#include "Pt.h"
#include "Qt3DSDMMetaData.h"
+#include "Qt3DSDMAnimation.h"
#include "Qt3DSDMComposerTypeDefinitions.h"
class CDoc;
@@ -294,6 +295,8 @@ public:
qt3dsdm::Qt3DSDMPropertyHandle GetAggregateInstancePropertyByName(
qt3dsdm::Qt3DSDMInstanceHandle inInstance,
const qt3dsdm::TCharStr &inStr);
+ bool hasAggregateInstanceProperty(qt3dsdm::Qt3DSDMInstanceHandle inInstance,
+ qt3dsdm::Qt3DSDMPropertyHandle inProperty) const;
// helpers
void BeginRender(); // enable cache to increase performance
diff --git a/src/Authoring/Client/Code/Core/Doc/Doc.cpp b/src/Authoring/Client/Code/Core/Doc/Doc.cpp
index c2cc681f..75643a94 100644
--- a/src/Authoring/Client/Code/Core/Doc/Doc.cpp
+++ b/src/Authoring/Client/Code/Core/Doc/Doc.cpp
@@ -2501,6 +2501,14 @@ void CDoc::SavePresentationFile(CBufferedOutputStream *inOutputStream)
CDOMSerializer::Write(*theWriter.GetTopElement(), theStream);
}
+bool CDoc::canSetKeyframeInterpolation() const
+{
+ if (m_KeyframesManager)
+ return m_KeyframesManager->canSetKeyframeInterpolation();
+
+ return false;
+}
+
void CDoc::SetKeyframeInterpolation()
{
if (m_KeyframesManager)
diff --git a/src/Authoring/Client/Code/Core/Doc/Doc.h b/src/Authoring/Client/Code/Core/Doc/Doc.h
index 47f25fc8..a12df7cb 100644
--- a/src/Authoring/Client/Code/Core/Doc/Doc.h
+++ b/src/Authoring/Client/Code/Core/Doc/Doc.h
@@ -277,6 +277,7 @@ public:
bool canPasteObjects() const;
bool canPasteKeyframes() const;
bool canPasteActions() const;
+ bool canSetKeyframeInterpolation() const;
bool canPaste() const; // objects, keyframes, or actions
bool canCopy() const; // objects, keyframes, or actions
diff --git a/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp b/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp
index 6231e48e..d0be8e64 100644
--- a/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp
+++ b/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp
@@ -92,6 +92,7 @@
#include "StudioProjectSettings.h"
#include "StudioApp.h"
#include "StudioUtils.h"
+#include "Qt3DSDMHandles.h"
namespace {
@@ -2827,15 +2828,25 @@ public:
void SetKeyframeTime(TKeyframeHandle inKeyframe, long inTime) override
{
- float theTimeinSecs = static_cast<float>(inTime) / 1000.f;
+ float timeInSecs = static_cast<float>(inTime) / 1000.f;
// round off to 4 decimal place to workaround precision issues
// TODO: fix this, either all talk float OR long. choose one.
- theTimeinSecs = ceilf(theTimeinSecs * 10000.0f) / 10000.0f;
- TKeyframe theData = m_AnimationCore.GetKeyframeData(inKeyframe);
- // Function programming paradigm, returns new value instead of changing
- // current value.
- theData = qt3dsdm::SetKeyframeSeconds(theData, theTimeinSecs);
- m_AnimationCore.SetKeyframeData(inKeyframe, theData);
+ timeInSecs = ceilf(timeInSecs * 10000.0f) / 10000.0f;
+ TKeyframe kfData = m_AnimationCore.GetKeyframeData(inKeyframe);
+
+ // offset control points for bezier keyframes
+ offsetBezier(kfData, timeInSecs - GetKeyframeSeconds(kfData));
+
+ // Functional programming paradigm, returns new value instead of changing current value.
+ kfData = qt3dsdm::SetKeyframeSeconds(kfData, timeInSecs);
+ m_AnimationCore.SetKeyframeData(inKeyframe, kfData);
+ }
+
+ void setBezierKeyframeValues(const QVector<std::pair<qt3dsdm::Qt3DSDMKeyframeHandle,
+ TKeyframe>> &changedKfs) override
+ {
+ for (auto kf : changedKfs)
+ m_AnimationCore.SetKeyframeData(kf.first, kf.second);
}
void DeleteAllKeyframes(Qt3DSDMAnimationHandle inAnimation) override
@@ -2854,31 +2865,31 @@ public:
const wchar_t *propName, long subIndex, EAnimationType animType,
const float *keyframeValues, long numValues, bool /*inUserEdited*/) override
{
- Qt3DSDMPropertyHandle propHdl =
- m_DataCore.GetAggregateInstancePropertyByName(instance, propName);
- if (propHdl.Valid() == false) {
+ Qt3DSDMPropertyHandle property = m_DataCore.GetAggregateInstancePropertyByName(instance,
+ propName);
+ if (!property.Valid()) {
QT3DS_ASSERT(false);
return 0;
}
- if (inSlide.Valid() == false) {
+ if (!inSlide.Valid()) {
Qt3DSDMSlideHandle theSlide = m_SlideSystem.GetAssociatedSlide(instance);
- if (theSlide.Valid() == false) {
+ if (!theSlide.Valid()) {
assert(0);
return 0;
}
- if (m_SlideSystem.IsPropertyLinked(instance, propHdl))
+ if (m_SlideSystem.IsPropertyLinked(instance, property))
theSlide = m_SlideSystem.GetMasterSlide(theSlide);
inSlide = theSlide;
}
Qt3DSDMAnimationHandle animHandle =
- m_AnimationCore.GetAnimation(inSlide, instance, propHdl, subIndex);
+ m_AnimationCore.GetAnimation(inSlide, instance, property, subIndex);
- if (animHandle.Valid() == true)
+ if (animHandle.Valid())
m_AnimationCore.DeleteAnimation(animHandle);
animHandle =
- m_AnimationCore.CreateAnimation(inSlide, instance, propHdl, subIndex, animType, false);
+ m_AnimationCore.CreateAnimation(inSlide, instance, property, subIndex, animType, false);
long theStartTime = GetTimeRange(instance).first;
long theTimeOffsetInSeconds = long(theStartTime / 1000.f);
diff --git a/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.cpp b/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.cpp
index e11a441e..b0d4c626 100644
--- a/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.cpp
+++ b/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.cpp
@@ -121,7 +121,7 @@ template <typename TOperator>
static void HandleKeyframe(SLinearKeyframe &inKeyframe, TOperator &inOperator)
{
inOperator(inKeyframe.m_KeyframeSeconds);
- inOperator(inKeyframe.m_KeyframeSeconds);
+ inOperator(inKeyframe.m_KeyframeValue);
}
template <typename TOperator>
diff --git a/src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h b/src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h
index d49f8062..d1b655de 100644
--- a/src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h
+++ b/src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h
@@ -307,6 +307,8 @@ public:
virtual bool RemoveAnimation(TSlideHandle inSlide, TInstanceHandle instance,
const wchar_t *propName, long subIndex) = 0;
virtual void SetKeyframeTime(TKeyframeHandle inKeyframe, long inTimeInMilliseconds) = 0;
+ virtual void setBezierKeyframeValues(const QVector<std::pair<TKeyframeHandle,
+ qt3dsdm::TKeyframe>> &changedKfs) = 0;
virtual void DeleteAllKeyframes(Qt3DSDMAnimationHandle inAnimation) = 0;
virtual void KeyframeProperty(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty,
bool inDoDiffValue) = 0;
diff --git a/src/Authoring/Client/Code/Core/Doc/IKeyframesManager.h b/src/Authoring/Client/Code/Core/Doc/IKeyframesManager.h
index df028c3f..692e7d0c 100644
--- a/src/Authoring/Client/Code/Core/Doc/IKeyframesManager.h
+++ b/src/Authoring/Client/Code/Core/Doc/IKeyframesManager.h
@@ -35,10 +35,11 @@ class IKeyframesManager
public:
virtual ~IKeyframesManager() {}
- virtual bool HasSelectedKeyframes() = 0;
- virtual bool HasDynamicKeyframes() = 0;
- virtual bool CanPerformKeyframeCopy() = 0;
- virtual bool CanPerformKeyframePaste() = 0;
+ virtual bool HasSelectedKeyframes() const = 0;
+ virtual bool HasDynamicKeyframes() const = 0;
+ virtual bool CanPerformKeyframeCopy() const = 0;
+ virtual bool CanPerformKeyframePaste() const = 0;
+ virtual bool canSetKeyframeInterpolation() const = 0;
virtual void CopyKeyframes() = 0;
virtual bool RemoveKeyframes(bool inPerformCopy) = 0;
virtual void PasteKeyframes() = 0;
diff --git a/src/Authoring/Client/Code/Core/Utility/StudioPreferences.cpp b/src/Authoring/Client/Code/Core/Utility/StudioPreferences.cpp
index d9ed32c4..6d07d23b 100644
--- a/src/Authoring/Client/Code/Core/Utility/StudioPreferences.cpp
+++ b/src/Authoring/Client/Code/Core/Utility/StudioPreferences.cpp
@@ -811,6 +811,11 @@ QColor CStudioPreferences::GetZAxisColor()
return s_zAxisColor;
}
+QColor CStudioPreferences::getBezierControlColor()
+{
+ return QColor("#f4bd04");
+}
+
/**
* Colors for rulers and guides
*/
diff --git a/src/Authoring/Client/Code/Core/Utility/StudioPreferences.h b/src/Authoring/Client/Code/Core/Utility/StudioPreferences.h
index 99e2d02f..494b2c05 100644
--- a/src/Authoring/Client/Code/Core/Utility/StudioPreferences.h
+++ b/src/Authoring/Client/Code/Core/Utility/StudioPreferences.h
@@ -149,6 +149,7 @@ public:
static QColor GetXAxisColor();
static QColor GetYAxisColor();
static QColor GetZAxisColor();
+ static QColor getBezierControlColor();
static ::CColor GetRulerBackgroundColor();
static ::CColor GetRulerTickColor();
diff --git a/src/Authoring/Qt3DStudio/Application/StudioApp.cpp b/src/Authoring/Qt3DStudio/Application/StudioApp.cpp
index cc8b07cb..7bf9c93c 100644
--- a/src/Authoring/Qt3DStudio/Application/StudioApp.cpp
+++ b/src/Authoring/Qt3DStudio/Application/StudioApp.cpp
@@ -39,7 +39,6 @@
#include "qtlocalpeer.h"
#include "TimelineWidget.h"
#include "SlideView.h"
-#include "IKeyframesManager.h"
#include "PresentationFile.h"
#include "EditPresentationIdDlg.h"
#include "Qt3DSDMWStrOps.h"
diff --git a/src/Authoring/Qt3DStudio/MainFrm.cpp b/src/Authoring/Qt3DStudio/MainFrm.cpp
index 7626d408..3773feba 100644
--- a/src/Authoring/Qt3DStudio/MainFrm.cpp
+++ b/src/Authoring/Qt3DStudio/MainFrm.cpp
@@ -32,7 +32,6 @@
#include "StudioConst.h"
#include "SceneView.h"
#include "StudioApp.h"
-#include "IKeyframesManager.h"
#include "Dialogs.h"
#include "StudioPreferencesPropSheet.h"
#include "StudioPreferences.h"
@@ -677,7 +676,8 @@ void CMainFrame::OnUpdateTimelineDeleteSelectedKeyframes()
*/
void CMainFrame::OnUpdateTimelineSetInterpolation()
{
- m_ui->actionSet_Interpolation->setEnabled(getTimelineWidget()->hasSelectedKeyframes());
+ bool enabled = g_StudioApp.GetCore()->GetDoc()->canSetKeyframeInterpolation();
+ m_ui->actionSet_Interpolation->setEnabled(enabled);
}
/**
diff --git a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/ITimelineItemProperty.h b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/ITimelineItemProperty.h
index 72488480..4754bb0d 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/ITimelineItemProperty.h
+++ b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/ITimelineItemProperty.h
@@ -28,12 +28,11 @@
****************************************************************************/
#ifndef INCLUDED_ITIMELINE_ITEM_PROPERTY_H
-#define INCLUDED_ITIMELINE_ITEM_PROPERTY_H 1
-
-#pragma once
+#define INCLUDED_ITIMELINE_ITEM_PROPERTY_H
#include "Qt3DSDMMetaData.h"
#include "Qt3DSString.h"
+#include "Qt3DSDMAnimation.h"
class RowTree;
class IKeyframe;
@@ -60,11 +59,15 @@ public:
virtual void setRowTree(RowTree *row) = 0;
virtual RowTree *getRowTree() const = 0;
+ virtual qt3dsdm::Qt3DSDMPropertyHandle getPropertyHandle() const = 0;
+ virtual std::vector<qt3dsdm::Qt3DSDMAnimationHandle> animationHandles() const = 0;
+ virtual qt3dsdm::EAnimationType animationType() const = 0;
+
// Keyframes
virtual IKeyframe *GetKeyframeByTime(long inTime) const = 0;
virtual IKeyframe *GetKeyframeByIndex(long inIndex) const = 0;
virtual long GetKeyframeCount() const = 0;
- virtual long GetChannelCount() const = 0;
+ virtual size_t GetChannelCount() const = 0;
virtual float GetChannelValueAtTime(long inChannelIndex, long inTime) = 0;
virtual void SetChannelValueAtTime(long inChannelIndex, long inTime, float inValue) = 0;
virtual bool IsDynamicAnimation() = 0;
diff --git a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/PasteKeyframesCommandHelper.h b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/PasteKeyframesCommandHelper.h
index ead15d2e..f6330cc0 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/PasteKeyframesCommandHelper.h
+++ b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/PasteKeyframesCommandHelper.h
@@ -28,13 +28,8 @@
****************************************************************************/
#ifndef INCLUDED_PASTE_KEYFRAME_COMMAND_HELPER_H
-#define INCLUDED_PASTE_KEYFRAME_COMMAND_HELPER_H 1
+#define INCLUDED_PASTE_KEYFRAME_COMMAND_HELPER_H
-#pragma once
-
-//==============================================================================
-// Include
-//==============================================================================
#include "CmdDataModelInsertKeyframe.h"
#include "Qt3DSDMPropertyDefinition.h"
#include "Qt3DSDMDataCore.h"
@@ -48,7 +43,7 @@ protected:
typedef std::vector<CCmdDataModelInsertKeyframe::STimeKeyframeData> TCopiedKeyframeList;
TCopiedKeyframeList m_CopiedKeyframeList;
-public: // Construction
+public:
CPasteKeyframeCommandHelper() {}
~CPasteKeyframeCommandHelper() {}
@@ -76,40 +71,24 @@ public: // Construction
{
using namespace qt3dsdm;
- CCmdDataModelInsertKeyframe *theInsertKeyframesCommand = nullptr;
- TCopiedKeyframeList::iterator theIter = m_CopiedKeyframeList.begin();
- qt3dsdm::IPropertySystem *thePropertySystem = inDoc->GetStudioSystem()->GetPropertySystem();
- CClientDataModelBridge *theBridge = inDoc->GetStudioSystem()->GetClientDataModelBridge();
+ CCmdDataModelInsertKeyframe *insertKeyframesCmd = nullptr;
+ qt3dsdm::IPropertySystem *propSys = inDoc->GetStudioSystem()->GetPropertySystem();
+ CClientDataModelBridge *bridge = inDoc->GetStudioSystem()->GetClientDataModelBridge();
- for (; theIter != m_CopiedKeyframeList.end(); ++theIter) {
- TCharStr thePropertyName = thePropertySystem->GetName(theIter->m_Property);
- DataModelDataType::Value thePropertyType =
- thePropertySystem->GetDataType(theIter->m_Property);
- Qt3DSDMPropertyHandle theTargetPropertyHandle =
- theBridge->GetAggregateInstancePropertyByName(inTargetInstance, thePropertyName);
- if (theTargetPropertyHandle.Valid()) // property exists on target
- {
- // sanity check for type match
- DataModelDataType::Value theTargetPropertyType =
- thePropertySystem->GetDataType(theTargetPropertyHandle);
- if (theTargetPropertyType == thePropertyType) {
- // 2. Offset keyframe time by current view time
- double milliseconds = theIter->m_KeyframeTime * 1000.0;
- double theTimeInMilliseconds = milliseconds + inTimeOffsetInMilliseconds;
- float theTimeInSeconds = static_cast<float>(theTimeInMilliseconds / 1000.0);
+ for (auto &kfData : m_CopiedKeyframeList) {
+ // check property exists on target
+ if (bridge->hasAggregateInstanceProperty(inTargetInstance, kfData.m_Property)) {
+ if (!insertKeyframesCmd)
+ insertKeyframesCmd = new CCmdDataModelInsertKeyframe(inDoc, inTargetInstance);
- if (!theInsertKeyframesCommand)
- theInsertKeyframesCommand = new CCmdDataModelInsertKeyframe(
- inDoc, inTargetInstance, theTargetPropertyHandle, theTimeInSeconds,
- theIter->m_Infos, theIter->m_ValidInfoCount);
- else
- theInsertKeyframesCommand->AddKeyframeData(
- theTargetPropertyHandle, theTimeInSeconds, theIter->m_Infos,
- theIter->m_ValidInfoCount);
- }
+ // Offset keyframe time by current view time (time in seconds)
+ float time = kfData.m_KeyframeTime + inTimeOffsetInMilliseconds / 1000.f;
+ insertKeyframesCmd->AddKeyframeData(kfData.m_Property, time, kfData.m_Infos,
+ kfData.m_ValidInfoCount);
}
}
- return theInsertKeyframesCommand;
+
+ return insertKeyframesCmd;
}
void Clear() { m_CopiedKeyframeList.clear(); }
diff --git a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemProperty.cpp b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemProperty.cpp
index 0249bd13..f863435c 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemProperty.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemProperty.cpp
@@ -131,6 +131,11 @@ qt3dsdm::Qt3DSDMPropertyHandle Qt3DSDMTimelineItemProperty::getPropertyHandle()
return m_PropertyHandle;
}
+std::vector<qt3dsdm::Qt3DSDMAnimationHandle> Qt3DSDMTimelineItemProperty::animationHandles() const
+{
+ return m_AnimationHandles;
+}
+
// Type doesn't change and due to the logic required to figure this out, cache it.
void Qt3DSDMTimelineItemProperty::InitializeCachedVariables(qt3dsdm::Qt3DSDMInstanceHandle inInstance)
{
@@ -190,7 +195,8 @@ void CompareAndSet(const Qt3DSDMTimelineKeyframe *inKeyframe, float &outRetValue
outRetValue = theValue;
}
-// return the max value of the current set of keyframes
+// returns the max keyframe value in a property. For bezier keyframes this includes the control
+// points values as well
float Qt3DSDMTimelineItemProperty::GetMaximumValue() const
{
float theRetVal = FLT_MIN;
@@ -200,7 +206,8 @@ float Qt3DSDMTimelineItemProperty::GetMaximumValue() const
return theRetVal;
}
-// return the min value of the current set of keyframes
+// returns the min keyframe value in a property. For bezier keyframes this includes the control
+// points values as well
float Qt3DSDMTimelineItemProperty::GetMinimumValue() const
{
float theRetVal = FLT_MAX;
@@ -267,9 +274,9 @@ long Qt3DSDMTimelineItemProperty::GetKeyframeCount() const
return (long)m_Keyframes.size();
}
-long Qt3DSDMTimelineItemProperty::GetChannelCount() const
+size_t Qt3DSDMTimelineItemProperty::GetChannelCount() const
{
- return (long)m_AnimationHandles.size();
+ return m_AnimationHandles.size();
}
float Qt3DSDMTimelineItemProperty::GetChannelValueAtTime(long inChannelIndex, long inTime)
@@ -357,7 +364,15 @@ bool Qt3DSDMTimelineItemProperty::IsDynamicAnimation()
return m_Keyframes.size() > 0 && m_Keyframes[0]->IsDynamic();
}
-//=============================================================================
+EAnimationType Qt3DSDMTimelineItemProperty::animationType() const
+{
+ if (m_AnimationHandles.empty())
+ return EAnimationTypeNone;
+
+ IAnimationCore *animCore = m_TransMgr->GetStudioSystem()->GetAnimationCore();
+ return animCore->GetAnimationInfo(m_AnimationHandles[0]).m_AnimationType;
+}
+
/**
* For updating the UI when keyframes are added/updated/deleted.
*/
diff --git a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemProperty.h b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemProperty.h
index 1b1524e4..ff508ae8 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemProperty.h
+++ b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemProperty.h
@@ -36,6 +36,7 @@
#include "Qt3DSDMTimelineKeyframe.h"
#include "Qt3DSDMTimeline.h"
#include "Qt3DSDMPropertyDefinition.h"
+#include "Qt3DSDMAnimation.h"
class RowTree;
class CTimelineTranslationManager;
@@ -52,8 +53,8 @@ class Qt3DSDMTimelineItemProperty : public ITimelineItemProperty
{
public:
Qt3DSDMTimelineItemProperty(CTimelineTranslationManager *inTransMgr,
- qt3dsdm::Qt3DSDMPropertyHandle inPropertyHandle,
- qt3dsdm::Qt3DSDMInstanceHandle inInstance);
+ qt3dsdm::Qt3DSDMPropertyHandle inPropertyHandle,
+ qt3dsdm::Qt3DSDMInstanceHandle inInstance);
virtual ~Qt3DSDMTimelineItemProperty();
// ITimelineProperty
@@ -67,23 +68,25 @@ public:
IKeyframe *GetKeyframeByTime(long inTime) const override;
IKeyframe *GetKeyframeByIndex(long inIndex) const override;
long GetKeyframeCount() const override;
- long GetChannelCount() const override;
+ size_t GetChannelCount() const override;
float GetChannelValueAtTime(long inChannelIndex, long inTime) override;
void SetChannelValueAtTime(long inChannelIndex, long inTime, float inValue) override;
bool IsDynamicAnimation() override;
-
void setRowTree(RowTree *rowTree) override;
RowTree *getRowTree() const override;
+ qt3dsdm::Qt3DSDMPropertyHandle getPropertyHandle() const override;
+ std::vector<qt3dsdm::Qt3DSDMAnimationHandle> animationHandles() const override;
bool RefreshKeyframe(qt3dsdm::Qt3DSDMKeyframeHandle inKeyframe,
ETimelineKeyframeTransaction inTransaction);
IKeyframe *GetKeyframeByHandle(qt3dsdm::Qt3DSDMKeyframeHandle inKeyframe);
void RefreshKeyFrames(void);
-
- qt3dsdm::Qt3DSDMPropertyHandle getPropertyHandle() const;
+ qt3dsdm::EAnimationType animationType() const override;
protected:
+ using TKeyframeList = std::vector<Qt3DSDMTimelineKeyframe *>;
+
void InitializeCachedVariables(qt3dsdm::Qt3DSDMInstanceHandle inInstance);
bool CreateKeyframeIfNonExistent(qt3dsdm::Qt3DSDMKeyframeHandle inKeyframe,
qt3dsdm::Qt3DSDMAnimationHandle inOwningAnimation);
@@ -93,9 +96,6 @@ protected:
void CreateKeyframes();
void ReleaseKeyframes();
-protected:
- typedef std::vector<Qt3DSDMTimelineKeyframe *> TKeyframeList;
-
qt3dsdm::Qt3DSDMInstanceHandle m_InstanceHandle;
qt3dsdm::Qt3DSDMPropertyHandle m_PropertyHandle;
CTimelineTranslationManager *m_TransMgr;
diff --git a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineKeyframe.cpp b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineKeyframe.cpp
index ae7e2035..d8d7aad3 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineKeyframe.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineKeyframe.cpp
@@ -194,30 +194,52 @@ void Qt3DSDMTimelineKeyframe::GetKeyframeHandles(TKeyframeHandleList &outList) c
}
void CompareAndSet(Qt3DSDMKeyframeHandle inKeyframe, IAnimationCore *inAnimationCore,
- float &outRetValue, bool inGreaterThan)
-{
- TKeyframe theKeyframeData = inAnimationCore->GetKeyframeData(inKeyframe);
- float theValue = KeyframeValueValue(theKeyframeData);
- if ((inGreaterThan && theValue > outRetValue) || (!inGreaterThan && theValue < outRetValue))
- outRetValue = theValue;
+ float &ioRetValue, bool inGreaterThan)
+{
+ TKeyframe keyframeData = inAnimationCore->GetKeyframeData(inKeyframe);
+ float value = KeyframeValueValue(keyframeData);
+ if ((inGreaterThan && value > ioRetValue) || (!inGreaterThan && value < ioRetValue))
+ ioRetValue = value;
+
+ // for bezier keyframes compare tangents in/out also
+ if (keyframeData.getType() == qt3dsdm::EAnimationTypeBezier) {
+ float inTime, inValue, outTime, outValue;
+ getBezierValues(keyframeData, inTime, inValue, outTime, outValue);
+
+ if (!inAnimationCore->IsFirstKeyframe(inKeyframe) // check tangent-in value
+ && ((inGreaterThan && inValue > ioRetValue)
+ || (!inGreaterThan && inValue < ioRetValue))) {
+ ioRetValue = inValue;
+ }
+
+ if (!inAnimationCore->IsLastKeyframe(inKeyframe) // check tangent-out value
+ && ((inGreaterThan && outValue > ioRetValue)
+ || (!inGreaterThan && outValue < ioRetValue))) {
+ ioRetValue = outValue;
+ }
+ }
}
+// returns the max keyframe channel value. For bezier keyframes this includes the control
+// points values as well
float Qt3DSDMTimelineKeyframe::GetMaxValue() const
{
- IAnimationCore *theAnimationCore = m_Doc->GetStudioSystem()->GetAnimationCore();
+ IAnimationCore *animCore = m_Doc->GetStudioSystem()->GetAnimationCore();
float theRetVal = FLT_MIN;
do_all(m_KeyframeHandles,
- std::bind(CompareAndSet, std::placeholders::_1, theAnimationCore,
- std::ref(theRetVal), true));
+ std::bind(CompareAndSet, std::placeholders::_1, animCore, std::ref(theRetVal), true));
+
return theRetVal;
}
+// returns the min keyframe channel value. For bezier keyframes this includes the control
+// points values as well
float Qt3DSDMTimelineKeyframe::GetMinValue() const
{
- IAnimationCore *theAnimationCore = m_Doc->GetStudioSystem()->GetAnimationCore();
+ IAnimationCore *animCore = m_Doc->GetStudioSystem()->GetAnimationCore();
float theRetVal = FLT_MAX;
do_all(m_KeyframeHandles,
- std::bind(CompareAndSet, std::placeholders::_1, theAnimationCore,
- std::ref(theRetVal), false));
+ std::bind(CompareAndSet, std::placeholders::_1, animCore, std::ref(theRetVal), false));
+
return theRetVal;
}
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/Keyframe.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/Keyframe.h
index 7e4ea614..3cbd9383 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/Keyframe.h
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/Keyframe.h
@@ -37,9 +37,9 @@ struct Keyframe
{
Keyframe(long time, RowTimeline *propRow)
: time(time)
+ , propertyType(propRow->rowTree()->propertyType())
, rowProperty(propRow)
, rowMaster(propRow->parentRow())
- , propertyType(propRow->rowTree()->propertyType())
{}
bool selected() const
@@ -47,7 +47,7 @@ struct Keyframe
return binding && binding->IsSelected();
}
- long time;
+ long time; // millis
QString propertyType;
RowTimeline *rowProperty = nullptr;
RowTimeline *rowMaster = nullptr;
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/KeyframeManager.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/KeyframeManager.cpp
index 7b39b272..2432ce77 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/KeyframeManager.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/KeyframeManager.cpp
@@ -35,6 +35,7 @@
#include "StudioApp.h"
#include "Core.h"
#include "Doc.h"
+#include "SlideSystem.h"
#include "StudioClipboard.h"
#include "CmdDataModelRemoveKeyframe.h"
#include "CmdDataModelInsertKeyframe.h"
@@ -42,6 +43,7 @@
#include "ClientDataModelBridge.h"
#include "Bindings/OffsetKeyframesCommandHelper.h"
#include "Bindings/PasteKeyframesCommandHelper.h"
+#include "Bindings/ITimelineItemBinding.h"
#include "StudioPreferences.h"
#include "Dialogs.h"
#include "TimeEnums.h"
@@ -332,19 +334,14 @@ void KeyframeManager::copySelectedKeyframes()
}
qt3dsdm::SGetOrSetKeyframeInfo KeyframeManager::setKeyframeInfo(
- qt3dsdm::Qt3DSDMKeyframeHandle inKeyframe, qt3dsdm::IAnimationCore &inCore)
-{
- qt3dsdm::TKeyframe theKeyframeData = inCore.GetKeyframeData(inKeyframe);
- qt3dsdm::SEaseInEaseOutKeyframe keyframe =
- qt3dsdm::get<qt3dsdm::SEaseInEaseOutKeyframe>(theKeyframeData);
- bool isDynamic = false;
- if (inCore.IsFirstKeyframe(inKeyframe)) {
- isDynamic = inCore.GetAnimationInfo(inCore.GetAnimationForKeyframe(inKeyframe))
- .m_DynamicFirstKeyframe;
- }
+ qt3dsdm::Qt3DSDMKeyframeHandle keyframeHandle, qt3dsdm::IAnimationCore &animCore)
+{
+ qt3dsdm::TKeyframe keyframeData = animCore.GetKeyframeData(keyframeHandle);
+
+ bool isDynamic = animCore.IsFirstKeyframe(keyframeHandle) && animCore.GetAnimationInfo(
+ animCore.GetAnimationForKeyframe(keyframeHandle)).m_DynamicFirstKeyframe;
- return qt3dsdm::SGetOrSetKeyframeInfo(keyframe.m_KeyframeValue, keyframe.m_EaseIn,
- keyframe.m_EaseOut, isDynamic);
+ return qt3dsdm::SGetOrSetKeyframeInfo(keyframeData, isDynamic);
}
void KeyframeManager::pasteKeyframes()
@@ -483,23 +480,33 @@ void KeyframeManager::RollbackChangedKeyframes()
row->updateKeyframes();
}
-// IKeyframesManager interface
-bool KeyframeManager::HasSelectedKeyframes()
+bool KeyframeManager::HasSelectedKeyframes() const
{
return hasSelectedKeyframes();
}
-bool KeyframeManager::HasDynamicKeyframes()
+bool KeyframeManager::HasDynamicKeyframes() const
{
return false; // Mahmoud_TODO: implement
}
-bool KeyframeManager::CanPerformKeyframeCopy()
+bool KeyframeManager::CanPerformKeyframeCopy() const
{
return !m_selectedKeyframes.empty() && m_selectedKeyframesMasterRows.count() == 1;
}
-bool KeyframeManager::CanPerformKeyframePaste()
+bool KeyframeManager::canSetKeyframeInterpolation() const
+{
+ for (Keyframe *kf : qAsConst(m_selectedKeyframes)) {
+ auto animType = kf->rowProperty->rowTree()->propBinding()->animationType();
+ if (animType == qt3dsdm::EAnimationTypeEaseInOut)
+ return true;
+ }
+
+ return false;
+}
+
+bool KeyframeManager::CanPerformKeyframePaste() const
{
if (m_pasteKeyframeCommandHelper && m_pasteKeyframeCommandHelper->HasCopiedKeyframes()) {
qt3dsdm::Qt3DSDMInstanceHandle theSelectedInstance =
@@ -533,36 +540,36 @@ void KeyframeManager::SetKeyframeInterpolation()
if (!hasSelectedKeyframes())
return;
- float theEaseIn = 0;
- float theEaseOut = 0;
- if (CStudioPreferences::GetInterpolation())
- theEaseIn = theEaseOut = 100;
-
- CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
- IAnimationCore *theAnimationCore = theDoc->GetStudioSystem()->GetAnimationCore();
+ CDoc *doc = g_StudioApp.GetCore()->GetDoc();
+ IAnimationCore *animCore = doc->GetStudioSystem()->GetAnimationCore();
- if (!m_selectedKeyframes.empty()) {
- Qt3DSDMTimelineKeyframe *theTimelineKeyframe = m_selectedKeyframes.front()->binding;
- Qt3DSDMTimelineKeyframe::TKeyframeHandleList theKeyframeHandles;
- theTimelineKeyframe->GetKeyframeHandles(theKeyframeHandles);
- TKeyframe theKeyframeData = theAnimationCore->GetKeyframeData(theKeyframeHandles[0]);
- GetEaseInOutValues(theKeyframeData, theEaseIn, theEaseOut);
+ // find the first easing keyframe and use it to get the current easing values
+ auto firstEaseKeyframeIter = m_selectedKeyframes.begin();
+ while ((*firstEaseKeyframeIter)->rowProperty->rowTree()->propBinding()->animationType()
+ != EAnimationTypeEaseInOut) {
+ firstEaseKeyframeIter++;
}
- if (g_StudioApp.GetDialogs()->PromptForKeyframeInterpolation(theEaseIn, theEaseOut)) {
- // Note: Having "editor" variable here is important as its destructor
- // creates proper transaction
- Q3DStudio::ScopedDocumentEditor editor(*theDoc, QObject::tr("Set Keyframe Interpolation"),
+ Qt3DSDMTimelineKeyframe::TKeyframeHandleList keyframeHandles;
+ (*firstEaseKeyframeIter)->binding->GetKeyframeHandles(keyframeHandles);
+
+ TKeyframe keyframeData = animCore->GetKeyframeData(keyframeHandles[0]);
+
+ float easeIn = CStudioPreferences::GetInterpolation() ? 100 : 0;
+ float easeOut = CStudioPreferences::GetInterpolation() ? 100 : 0;
+ GetEaseInOutValues(keyframeData, easeIn, easeOut);
+
+ if (g_StudioApp.GetDialogs()->displayKeyframeInterpolation(easeIn, easeOut)) {
+ // Having "editor" variable here is important as its destructor creates proper transaction
+ Q3DStudio::ScopedDocumentEditor editor(*doc, QObject::tr("Set Keyframe Interpolation"),
__FILE__, __LINE__);
for (Keyframe *keyframe : qAsConst(m_selectedKeyframes)) {
- Qt3DSDMTimelineKeyframe *theTimelineKeyframe = keyframe->binding;
- Qt3DSDMTimelineKeyframe::TKeyframeHandleList theKeyframeHandles;
- theTimelineKeyframe->GetKeyframeHandles(theKeyframeHandles);
- for (size_t i = 0; i < theKeyframeHandles.size(); ++i) {
- TKeyframe theKeyframeData =
- theAnimationCore->GetKeyframeData(theKeyframeHandles[i]);
- SetEaseInOutValues(theKeyframeData, theEaseIn, theEaseOut);
- theAnimationCore->SetKeyframeData(theKeyframeHandles[i], theKeyframeData);
+ Qt3DSDMTimelineKeyframe::TKeyframeHandleList keyframeHandles;
+ keyframe->binding->GetKeyframeHandles(keyframeHandles);
+ for (size_t i = 0; i < keyframeHandles.size(); ++i) {
+ TKeyframe keyframeData = animCore->GetKeyframeData(keyframeHandles[i]);
+ SetEaseInOutValues(keyframeData, easeIn, easeOut);
+ animCore->SetKeyframeData(keyframeHandles[i], keyframeData);
}
}
}
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/KeyframeManager.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/KeyframeManager.h
index 9c160687..0012c047 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/KeyframeManager.h
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/KeyframeManager.h
@@ -76,10 +76,11 @@ public:
void SetKeyframesDynamic(bool inDynamic) override;
void CommitChangedKeyframes() override;
void RollbackChangedKeyframes() override;
- bool HasSelectedKeyframes() override;
- bool HasDynamicKeyframes() override;
- bool CanPerformKeyframeCopy() override;
- bool CanPerformKeyframePaste() override;
+ bool HasSelectedKeyframes() const override;
+ bool HasDynamicKeyframes() const override;
+ bool CanPerformKeyframeCopy() const override;
+ bool CanPerformKeyframePaste() const override;
+ bool canSetKeyframeInterpolation() const override;
void CopyKeyframes() override;
bool RemoveKeyframes(bool inPerformCopy) override;
void PasteKeyframes() override;
@@ -89,12 +90,12 @@ public:
long getPressedKeyframeOffset() const;
private:
- qt3dsdm::SGetOrSetKeyframeInfo setKeyframeInfo(qt3dsdm::Qt3DSDMKeyframeHandle inKeyframe,
- qt3dsdm::IAnimationCore &inCore);
+ qt3dsdm::SGetOrSetKeyframeInfo setKeyframeInfo(qt3dsdm::Qt3DSDMKeyframeHandle keyframeHandle,
+ qt3dsdm::IAnimationCore &animCore);
long getMinSelectedKeyframesTime() const;
CPasteKeyframeCommandHelper *m_pasteKeyframeCommandHelper = nullptr;
- TimelineGraphicsScene *m_scene;
+ TimelineGraphicsScene *m_scene = nullptr;
QList<Keyframe *> m_selectedKeyframes;
QList<RowTimeline *> m_selectedKeyframesMasterRows;
};
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowTypes.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowTypes.h
index 58a93115..5facc147 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowTypes.h
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowTypes.h
@@ -35,8 +35,10 @@ enum class TimelineControlType {
None,
KeyFrame,
Duration,
- StartHandle,
- EndHandle
+ DurationStartHandle,
+ DurationEndHandle,
+ BezierInHandle,
+ BezierOutHandle
};
enum class TreeControlType {
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineConstants.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineConstants.h
index 61525718..c9036aba 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineConstants.h
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineConstants.h
@@ -33,7 +33,8 @@ namespace TimelineConstants
{
// Dimensions
const int ROW_H = 20;
- const int ROW_H_EXPANDED = 120; // property rows height when graph is shown
+ const int ROW_GRAPH_H = 120; // property row height when graph is shown
+ const int ROW_GRAPH_H_MAX = 300; // property row height when graph is shown maximized
const int ROW_SPACING = 2;
const int ROW_DEPTH_STEP = 15; // x-distance between 2 consecutive depths
const double RULER_SEC_W = 30; // width of 1 second section (at scale 1)
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp
index b4a52760..f33cf263 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp
@@ -32,6 +32,7 @@
#include "Ruler.h"
#include "PlayHead.h"
#include "RowTree.h"
+#include "RowTimelinePropertyGraph.h"
#include "RowMover.h"
#include "RowTimeline.h"
#include "TimelineConstants.h"
@@ -226,7 +227,7 @@ TimelineGraphicsScene::TimelineGraphicsScene(TimelineWidget *timelineWidget)
}
if (m_dragging) {
- if (m_clickedTimelineControlType == TimelineControlType::StartHandle) {
+ if (m_clickedTimelineControlType == TimelineControlType::DurationStartHandle) {
double visiblePtX = distance > 0 ? m_editedTimelineRow->getStartX() : 0;
if (distance > m_editedTimelineRow->getEndX())
visiblePtX += TimelineConstants::RULER_EDGE_OFFSET;
@@ -237,7 +238,8 @@ TimelineGraphicsScene::TimelineGraphicsScene(TimelineWidget *timelineWidget)
+ TimelineConstants::RULER_EDGE_OFFSET
+ visiblePtX,
m_editedTimelineRow->y(), 0, 0, 0, 0);
- } else if (m_clickedTimelineControlType == TimelineControlType::EndHandle) {
+ } else if (m_clickedTimelineControlType
+ == TimelineControlType::DurationEndHandle) {
long time = m_ruler->distanceToTime(distance);
double edgeMargin = 0;
if (time > TimelineConstants::MAX_SLIDE_TIME) {
@@ -466,19 +468,36 @@ void TimelineGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
g_StudioApp.setLastActiveView(m_widgetTimeline);
- if ((event->modifiers() & Qt::AltModifier) && !m_dragging) {
- if (event->button() == Qt::RightButton && !m_timelinePanning) {
- // Start zooming
- m_timelineZooming = true;
+ if ((event->modifiers() & Qt::AltModifier) && !m_dragging
+ && m_timelineAltModifierMode == TimelineAltModifierMode::None) {
+ if (event->button() == Qt::RightButton) {
+ // Start scaling
+ m_timelineAltModifierMode = TimelineAltModifierMode::ScaleTimeline;
m_pressScreenPos = event->screenPos();
event->accept();
return;
- } else if (event->button() == Qt::MiddleButton && !m_timelineZooming) {
+ } else if (event->button() == Qt::MiddleButton) {
// Start panning
- m_timelinePanning = true;
+ m_timelineAltModifierMode = TimelineAltModifierMode::PanTimeline;
m_pressPos = event->scenePos();
event->accept();
return;
+ } else if (event->button() == Qt::LeftButton) {
+ // Start property graph panning
+ m_pressPos = event->scenePos();
+ QGraphicsItem *item = getItemBelowType(TimelineItem::TypePlayHead,
+ itemAt(m_pressPos, {}), m_pressPos);
+ if (item && item->type() == TimelineItem::TypeRowTimeline) {
+ RowTimeline *rowTimeline = static_cast<RowTimeline *>(item);
+ if (rowTimeline->propertyGraph()) {
+ m_timelineAltModifierMode = TimelineAltModifierMode::PanPropertyGraph;
+ m_panProperyGraph = rowTimeline->propertyGraph();
+ m_panProperyGraph->startPan();
+ event->accept();
+ return;
+ }
+ }
+
}
}
@@ -570,11 +589,13 @@ void TimelineGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
m_rowManager->selectRow(m_editedTimelineRow->rowTree(), ctrlKeyDown);
// click position in ruler space
m_editedTimelineRow->startDurationMove(m_pressPos.x() - m_ruler->x());
- } else if (m_clickedTimelineControlType == TimelineControlType::StartHandle
- || m_clickedTimelineControlType == TimelineControlType::EndHandle) {
+ } else if (m_clickedTimelineControlType
+ == TimelineControlType::DurationStartHandle
+ || m_clickedTimelineControlType
+ == TimelineControlType::DurationEndHandle) {
m_editedTimelineRow->updateBoundChildren(
m_clickedTimelineControlType
- == TimelineControlType::StartHandle);
+ == TimelineControlType::DurationStartHandle);
}
m_autoScrollTimelineTimer.start();
}
@@ -594,9 +615,9 @@ void TimelineGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
void TimelineGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
- if (m_timelineZooming) {
- int deltaY = event->screenPos().y() - m_pressScreenPos.y();
+ if (m_timelineAltModifierMode == TimelineAltModifierMode::ScaleTimeline) {
int deltaX = event->screenPos().x() - m_pressScreenPos.x();
+ int deltaY = event->screenPos().y() - m_pressScreenPos.y();
// Zooming in when moving down/right.
int delta = -deltaX - deltaY;
const int threshold = 20;
@@ -607,24 +628,32 @@ void TimelineGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
m_widgetTimeline->toolbar()->onZoomOutButtonClicked();
m_pressScreenPos = event->screenPos();
}
- } else if (m_timelinePanning) {
+ } else if (m_timelineAltModifierMode == TimelineAltModifierMode::PanTimeline) {
int deltaX = event->scenePos().x() - m_pressPos.x();
QScrollBar *scrollbar = m_widgetTimeline->viewTimelineContent()->horizontalScrollBar();
scrollbar->setValue(scrollbar->value() - deltaX);
+ } else if (m_timelineAltModifierMode == TimelineAltModifierMode::PanPropertyGraph) {
+ qreal deltaY = event->scenePos().y() - m_pressPos.y();
+ m_panProperyGraph->pan(deltaY);
}
if (m_editedTimelineRow.isNull())
updateHoverStatus(event->scenePos());
- if (!m_dragging && !m_timelineZooming && !m_timelinePanning
- && m_pressPos != invalidPoint
- && (event->scenePos() - m_pressPos).manhattanLength() > 10) {
+ if (!m_dragging && m_timelineAltModifierMode == TimelineAltModifierMode::None
+ && m_pressPos != invalidPoint && (event->scenePos() - m_pressPos).manhattanLength() > 10) {
m_dragging = true;
}
bool shift = event->modifiers() & Qt::ShiftModifier;
if (m_dragging) {
- if (m_startRowMoverOnNextDrag || m_rowMover->isActive()) {
+ if (m_clickedTimelineControlType == TimelineControlType::BezierInHandle
+ || m_clickedTimelineControlType == TimelineControlType::BezierOutHandle) {
+ if (m_editedTimelineRow && m_editedTimelineRow->propertyGraph()) {
+ m_editedTimelineRow->propertyGraph()->updateBezierControlValue(
+ m_clickedTimelineControlType, event->scenePos());
+ }
+ } else if (m_startRowMoverOnNextDrag || m_rowMover->isActive()) {
// moving rows vertically (reorder/reparent)
if (m_startRowMoverOnNextDrag) {
m_startRowMoverOnNextDrag = false;
@@ -729,11 +758,11 @@ void TimelineGraphicsScene::resetMousePressParams()
m_selectionRect->end();
m_rowMover->end();
m_dragging = false;
- m_timelineZooming = false;
- m_timelinePanning = false;
m_startRowMoverOnNextDrag = false;
m_rulerPressed = false;
m_pressedKeyframe = nullptr;
+ m_panProperyGraph = nullptr;
+ m_timelineAltModifierMode = TimelineAltModifierMode::None;
m_clickedTimelineControlType = TimelineControlType::None;
m_editedTimelineRow.clear();
m_releaseSelectRow.clear();
@@ -797,16 +826,15 @@ void TimelineGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
if (m_rowMover->isActive()) { // moving rows (reorder/reparent)
commitMoveRows();
} else if (m_pressedKeyframe) {
- // update keyframe movement (time) to binding
m_keyframeManager->commitMoveSelectedKeyframes();
- } else if (m_clickedTimelineControlType == TimelineControlType::StartHandle) {
+ } else if (m_clickedTimelineControlType == TimelineControlType::DurationStartHandle) {
if (!m_editedTimelineRow.isNull()) {
ITimelineTimebar *timebar = m_editedTimelineRow->rowTree()->getBinding()
->GetTimelineItem()->GetTimebar();
timebar->ChangeTime(m_editedTimelineRow->getStartTime(), true);
timebar->CommitTimeChange();
}
- } else if (m_clickedTimelineControlType == TimelineControlType::EndHandle) {
+ } else if (m_clickedTimelineControlType == TimelineControlType::DurationEndHandle) {
if (!m_editedTimelineRow.isNull()) {
ITimelineTimebar *timebar = m_editedTimelineRow->rowTree()->getBinding()
->GetTimelineItem()->GetTimebar();
@@ -824,6 +852,9 @@ 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) {
+ m_editedTimelineRow->propertyGraph()->commitBezierEdit();
}
} else if (!m_rulerPressed && (!m_releaseSelectRow.isNull() || !itemAt(event->scenePos(),
QTransform()))) {
@@ -833,7 +864,7 @@ void TimelineGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
}
}
- if (m_timelineZooming)
+ if (m_timelineAltModifierMode == TimelineAltModifierMode::ScaleTimeline)
updateSnapSteps();
resetMousePressParams();
@@ -860,7 +891,7 @@ void TimelineGraphicsScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *even
if (item->type() == TimelineItem::TypeRowTree) {
RowTree *treeItem = static_cast<RowTree *>(item);
if (treeItem->isProperty())
- treeItem->togglePropertyExpanded();
+ treeItem->togglePropertyExpanded(scenePos);
} else if (item->type() == TimelineItem::TypeRowTreeLabelItem) {
RowTreeLabelItem *treeLabelItem = static_cast<RowTreeLabelItem *>(item);
if (treeLabelItem->parentRow()->isProperty()) {
@@ -901,6 +932,17 @@ void TimelineGraphicsScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *even
void TimelineGraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *wheelEvent)
{
+ // adjust property graph scale
+ if (wheelEvent->modifiers() & Qt::AltModifier) {
+ const QPointF pos = wheelEvent->scenePos();
+ QGraphicsItem *item = getItemBelowType(TimelineItem::TypePlayHead, itemAt(pos, {}), pos);
+ if (item && item->type() == TimelineItem::TypeRowTimeline) {
+ RowTimeline *rowTimeline = static_cast<RowTimeline *>(item);
+ if (rowTimeline->propertyGraph())
+ rowTimeline->propertyGraph()->adjustScale(wheelEvent->delta() > 0);
+ }
+ }
+
// Make sure drag states update on wheel scrolls done during drag
m_lastAutoScrollX = -1.0;
m_lastAutoScrollY = -1.0;
@@ -988,8 +1030,8 @@ void TimelineGraphicsScene::updateHoverStatus(const QPointF &scenePos)
if (item->type() == TimelineItem::TypeRowTimeline) {
RowTimeline *timelineItem = static_cast<RowTimeline *>(item);
TimelineControlType controlType = timelineItem->getClickedControl(scenePos);
- if (controlType == TimelineControlType::StartHandle
- || controlType == TimelineControlType::EndHandle) {
+ if (controlType == TimelineControlType::DurationStartHandle
+ || controlType == TimelineControlType::DurationEndHandle) {
setMouseCursor(CMouseCursor::CURSOR_RESIZE_LEFTRIGHT);
} else {
resetMouseCursor();
@@ -1071,6 +1113,9 @@ QGraphicsItem *TimelineGraphicsScene::getItemBelowType(TimelineItem::ItemType ty
QGraphicsItem *item,
const QPointF &scenePos) const
{
+ if (!item)
+ return nullptr;
+
if (item->type() == type) {
const QList<QGraphicsItem *> hoverItems = items(scenePos);
if (hoverItems.size() > 1)
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.h
index 146009ee..6de45ef9 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.h
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.h
@@ -50,7 +50,6 @@ class RowMover;
class RowManager;
class KeyframeManager;
class TimelineControl;
-class IKeyframesManager;
struct Keyframe;
QT_FORWARD_DECLARE_CLASS(QGraphicsLinearLayout)
@@ -111,6 +110,8 @@ protected:
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
private:
+ enum class TimelineAltModifierMode {None, ScaleTimeline, PanTimeline, PanPropertyGraph};
+
void commitMoveRows();
void updateHoverStatus(const QPointF &scenePos);
void snap(double &value, bool snapToPlayHead = true);
@@ -149,10 +150,10 @@ private:
bool m_rulerPressed = false;
Keyframe *m_pressedKeyframe = nullptr;
+ RowTimelinePropertyGraph *m_panProperyGraph = nullptr;
bool m_dragging = false;
bool m_startRowMoverOnNextDrag = false;
- bool m_timelineZooming = false;
- bool m_timelinePanning = false;
+ TimelineAltModifierMode m_timelineAltModifierMode = TimelineAltModifierMode::None;
TimelineControlType m_clickedTimelineControlType = TimelineControlType::None;
TreeControlType m_clickedTreeControlType = TreeControlType::None;
double m_pressPosInKeyframe;
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.cpp
index 967da5cb..5a2dca4d 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.cpp
@@ -164,8 +164,7 @@ TimelineWidget::TimelineWidget(const QSize &preferredSize, QWidget *parent)
layoutRoot->addWidget(m_toolbar);
setLayout(layoutRoot);
- g_StudioApp.GetCore()->GetDoc()->SetKeyframesManager(
- static_cast<IKeyframesManager *>(m_graphicsScene->keyframeManager()));
+ g_StudioApp.GetCore()->GetDoc()->SetKeyframesManager(m_graphicsScene->keyframeManager());
// connect graphics scene geometryChanged
connect(m_graphicsScene->widgetRoot(), &QGraphicsWidget::geometryChanged, this, [this]() {
@@ -585,7 +584,6 @@ void TimelineWidget::onAnimationCreated(qt3dsdm::Qt3DSDMInstanceHandle parentIns
Qt3DSDMTimelineItemBinding *binding = getBindingForHandle(parentInstance, m_binding);
if (binding) {
ITimelineItemProperty *propBinding = binding->GetPropertyBinding(property);
-
// create the binding if doesn't exist
if (!propBinding) {
propBinding = binding->GetOrCreatePropertyBinding(property);
@@ -624,6 +622,8 @@ void TimelineWidget::onAnimationDeleted(qt3dsdm::Qt3DSDMInstanceHandle parentIns
Qt3DSDMTimelineItemBinding *binding = getBindingForHandle(parentInstance, m_binding);
if (binding) {
ITimelineItemProperty *propBinding = binding->GetPropertyBinding(property);
+ // this is needed because onAnimationDeleted can be triggered for unlinked property on
+ // different slide in undo/redo situations
bool propAnimated = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()
->GetAnimationSystem()->IsPropertyAnimated(parentInstance, property);
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp
index 25b66911..c7cb5c51 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp
@@ -224,7 +224,8 @@ void RowTimeline::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio
}
if (m_propertyGraph) { // Property graph
- QRectF graphRect(edgeOffset, 0, widget->width(), currentHeight);
+ QRectF graphRect(rowTree()->m_scene->ruler()->viewportX(), 0,
+ widget->width(), currentHeight);
m_propertyGraph->paintGraphs(painter, graphRect);
}
@@ -498,7 +499,6 @@ void RowTimeline::updateKeyframesFromBinding(const QList<int> &properties)
for (int i = 0; i < child->m_PropBinding->GetKeyframeCount(); i++) {
Qt3DSDMTimelineKeyframe *kf = static_cast<Qt3DSDMTimelineKeyframe *>
(child->m_PropBinding->GetKeyframeByIndex(i));
-
Keyframe *kfUI = new Keyframe(kf->GetTime(), child->rowTimeline());
kfUI->binding = kf;
kfUI->dynamic = kf->IsDynamic();
@@ -567,12 +567,17 @@ void RowTimeline::updateKeyframes()
TimelineControlType RowTimeline::getClickedControl(const QPointF &scenePos) const
{
- if (!m_rowTree->hasDurationBar())
+ QPointF p = mapFromScene(scenePos.x(), scenePos.y());
+ p.setX(p.x() - TimelineConstants::RULER_EDGE_OFFSET);
+
+ if (!m_rowTree->hasDurationBar()) {
+ if (m_propertyGraph)
+ return m_propertyGraph->getClickedBezierControl(p);
+
return TimelineControlType::None;
+ }
if (!m_rowTree->locked()) {
- QPointF p = mapFromScene(scenePos.x(), scenePos.y());
- p.setX(p.x() - TimelineConstants::RULER_EDGE_OFFSET);
const int halfHandle = TimelineConstants::DURATION_HANDLE_W * .5;
// Never choose start handle if end time is zero, as you cannot adjust it in that case
@@ -585,10 +590,10 @@ TimelineControlType RowTimeline::getClickedControl(const QPointF &scenePos) cons
endHandle = !startHandle;
}
if (startHandle)
- return TimelineControlType::StartHandle;
+ return TimelineControlType::DurationStartHandle;
else if (endHandle)
- return TimelineControlType::EndHandle;
- else if (p.x() > m_startX && p.x() < m_endX && !rowTree()->locked())
+ return TimelineControlType::DurationEndHandle;
+ else if (p.x() > m_startX && p.x() < m_endX)
return TimelineControlType::Duration;
}
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.h
index 00c81696..30d60260 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.h
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.h
@@ -85,6 +85,7 @@ public:
QList<Keyframe *> getKeyframesInRange(const QRectF &rect) const;
QList<Keyframe *> keyframes() const;
void showToolTip(const QPointF &pos);
+ RowTimelinePropertyGraph *propertyGraph() const { return m_propertyGraph; }
protected:
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelineContextMenu.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelineContextMenu.cpp
index 7861bb19..02a7bf6c 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelineContextMenu.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelineContextMenu.cpp
@@ -32,6 +32,12 @@
#include "KeyframeManager.h"
#include "MainFrm.h"
#include "StudioApp.h"
+#include "Core.h"
+#include "Doc.h"
+#include "IDocumentEditor.h"
+#include "Qt3DSDMStudioSystem.h"
+#include "SlideSystem.h"
+#include "StudioPreferences.h"
#include "TimelineControl.h"
#include "Bindings/ITimelineItemBinding.h"
#include "TimelineGraphicsScene.h"
@@ -140,6 +146,26 @@ void RowTimelineContextMenu::initialize()
&RowTimelineContextMenu::setKeyframeTime);
addAction(m_setKeyframeTimeAction);
} else {
+ m_animType = addMenu(tr("Animation type"));
+ QAction *actionLinear = m_animType->addAction(tr("Linear"));
+ QAction *actionEase = m_animType->addAction(tr("Ease In/Out"));
+ QAction *actionBezier = m_animType->addAction(tr("Bezier"));
+ actionLinear->setData(qt3dsdm::EAnimationTypeLinear);
+ actionLinear->setCheckable(true);
+ actionEase->setData(qt3dsdm::EAnimationTypeEaseInOut);
+ actionEase->setCheckable(true);
+ actionBezier->setData(qt3dsdm::EAnimationTypeBezier);
+ actionBezier->setCheckable(true);
+ connect(m_animType, &QMenu::triggered, this, &RowTimelineContextMenu::onAnimTypeChange);
+ if (m_rowTree->isProperty()) {
+ qt3dsdm::EAnimationType animaType = m_rowTree->propBinding()->animationType();
+ if (animaType == qt3dsdm::EAnimationTypeLinear)
+ actionLinear->setChecked(true);
+ else if (animaType == qt3dsdm::EAnimationTypeEaseInOut)
+ actionEase->setChecked(true);
+ else if (animaType == qt3dsdm::EAnimationTypeBezier)
+ actionBezier->setChecked(true);
+ }
m_setTimeBarColorAction = new QAction(tr("Change Time Bar Color..."), this);
connect(m_setTimeBarColorAction, &QAction::triggered, this,
&RowTimelineContextMenu::changeTimeBarColor);
@@ -170,7 +196,12 @@ void RowTimelineContextMenu::showEvent(QShowEvent *event)
m_pasteKeyframesAction->setEnabled(m_keyframeManager->hasCopiedKeyframes());
m_deleteSelectedKeyframesAction->setEnabled(m_keyframeManager->hasSelectedKeyframes());
m_deleteRowKeyframesAction->setEnabled(!m_rowTree->rowTimeline()->keyframes().empty());
- if (!m_keyframe) {
+ if (m_keyframe) {
+ RowTree *row = propRow ? m_rowTree : m_keyframe->rowProperty->rowTree();
+ qt3dsdm::EAnimationType animaType = row->propBinding()->animationType();
+ m_setInterpolationAction->setEnabled(animaType == qt3dsdm::EAnimationTypeEaseInOut);
+ } else {
+ m_animType->setEnabled(propRow);
m_setTimeBarColorAction->setEnabled(m_rowTree->hasDurationBar());
m_setTimeBarTimeAction->setEnabled(m_rowTree->hasDurationBar());
}
@@ -178,6 +209,81 @@ void RowTimelineContextMenu::showEvent(QShowEvent *event)
QMenu::showEvent(event);
}
+void RowTimelineContextMenu::onAnimTypeChange(QAction *action)
+{
+ if (!action->isChecked())
+ return;
+
+ using namespace qt3dsdm;
+
+ // m_rowTree in this method is guaranteed to be a property row
+
+ CDoc *doc = g_StudioApp.GetCore()->GetDoc();
+ IAnimationCore *animCore = doc->GetAnimationCore();
+ ISlideSystem *slideSys = doc->GetStudioSystem()->GetSlideSystem();
+
+ Q3DStudio::ScopedDocumentEditor editor(*doc, tr("Set Animation Type"), __FILE__, __LINE__);
+
+ EAnimationType animType = EAnimationType(action->data().toInt());
+ Qt3DSDMInstanceHandle instance = m_rowTree->parentRow()->instance();
+ Qt3DSDMPropertyHandle property = m_rowTree->propBinding()->getPropertyHandle();
+ Qt3DSDMSlideHandle slide = slideSys->GetAssociatedSlide(instance);
+ TCharStr propType = doc->GetStudioSystem()->GetPropertySystem()->GetName(property);
+
+ std::vector<qt3dsdm::Qt3DSDMAnimationHandle> animHandles
+ = m_rowTree->propBinding()->animationHandles();
+ for (size_t i = 0; i < animHandles.size(); ++i) {
+ qt3dsdm::TKeyframeHandleList keyframeHandles;
+ animCore->GetKeyframes(animHandles[i], keyframeHandles);
+ if (animType == EAnimationTypeLinear) {
+ QVector<SLinearKeyframe> keyframes;
+ for (Qt3DSDMKeyframeHandle kfHandle : keyframeHandles) {
+ TKeyframe kfData = animCore->GetKeyframeData(kfHandle);
+ keyframes.append(SLinearKeyframe(KeyframeTime(kfData),
+ KeyframeValueValue(kfData)));
+ }
+ long numFloatsPerKeyframe = sizeof(SLinearKeyframe) / sizeof(float);
+ long numValues = long(keyframeHandles.size()) * numFloatsPerKeyframe;
+ editor->CreateOrSetAnimation(slide, instance, propType.wide_str(), long(i),
+ animType,
+ reinterpret_cast<float *>(keyframes.begin()),
+ numValues);
+ } else if (animType == EAnimationTypeEaseInOut) {
+ float easeIn = CStudioPreferences::GetInterpolation() ? 100 : 0;
+ float easeOut = CStudioPreferences::GetInterpolation() ? 100 : 0;
+ QVector<SEaseInEaseOutKeyframe> keyframes;
+ for (Qt3DSDMKeyframeHandle kfHandle : keyframeHandles) {
+ TKeyframe kfData = animCore->GetKeyframeData(kfHandle);
+ keyframes.append(SEaseInEaseOutKeyframe(KeyframeTime(kfData),
+ KeyframeValueValue(kfData),
+ easeIn, easeOut));
+ }
+ long numFloatsPerKeyframe = sizeof(SEaseInEaseOutKeyframe) / sizeof(float);
+ long numValues = long(keyframeHandles.size()) * numFloatsPerKeyframe;
+ editor->CreateOrSetAnimation(slide, instance, propType.wide_str(), long(i),
+ animType,
+ reinterpret_cast<float *>(keyframes.begin()),
+ numValues);
+ } else if (animType == EAnimationTypeBezier) {
+ QVector<SBezierKeyframe> keyframes;
+ for (Qt3DSDMKeyframeHandle kfHandle : keyframeHandles) {
+ TKeyframe kfData = animCore->GetKeyframeData(kfHandle);
+ float kfTime = KeyframeTime(kfData);
+ float kfValue = KeyframeValueValue(kfData);
+ keyframes.append(SBezierKeyframe(kfTime, kfValue,
+ kfTime - .5f, kfValue,
+ kfTime + .5f, kfValue));
+ }
+ long numFloatsPerKeyframe = sizeof(SBezierKeyframe) / sizeof(float);
+ long numValues = long(keyframeHandles.size()) * numFloatsPerKeyframe;
+ editor->CreateOrSetAnimation(slide, instance, propType.wide_str(), long(i),
+ animType,
+ reinterpret_cast<float *>(keyframes.begin()),
+ numValues);
+ }
+ }
+}
+
void RowTimelineContextMenu::insertKeyframe()
{
RowTree *destinationRowTree = nullptr;
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelineContextMenu.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelineContextMenu.h
index b8c2f922..d6b4a97f 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelineContextMenu.h
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelineContextMenu.h
@@ -65,6 +65,7 @@ private:
void changeTimeBarColor();
void setTimeBarTime();
void toggleDynamicKeyframes();
+ void onAnimTypeChange(QAction *action);
RowTree *m_rowTree = nullptr;
Keyframe *m_keyframe = nullptr;
@@ -81,6 +82,7 @@ private:
QAction *m_setTimeBarColorAction = nullptr;
QAction *m_setTimeBarTimeAction = nullptr;
QAction *m_dynamicKeyframesAction = nullptr;
+ QMenu *m_animType = nullptr;
TimelineControl *m_timelineControl = nullptr;
bool m_hasDynamicKeyframes = false;
};
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.cpp
index 3c82d73b..6c6c6f86 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.cpp
@@ -29,72 +29,355 @@
#include "RowTimelinePropertyGraph.h"
#include "RowTimeline.h"
#include "RowTree.h"
+#include "StudioApp.h"
+#include "Core.h"
+#include "Doc.h"
+#include "IDocumentEditor.h"
+#include "Qt3DSDMAnimation.h"
+#include "Keyframe.h"
#include "Ruler.h"
#include "TimelineGraphicsScene.h"
+#include "StudioPreferences.h"
+#include "HotKeys.h"
#include "Bindings/ITimelineItemProperty.h"
+using namespace qt3dsdm;
+using namespace TimelineConstants;
+
RowTimelinePropertyGraph::RowTimelinePropertyGraph(QObject *parent)
: QObject(parent)
+ , m_rowTimeline(static_cast<RowTimeline *>(parent))
+ , m_animCore(g_StudioApp.GetCore()->GetDoc()->GetAnimationCore())
{
- m_rowTimeline = static_cast<RowTimeline *>(parent);
+ m_fitCurveTimer.setInterval(10);
+
+ // smooth animation for when curve height change
+ connect(&m_fitCurveTimer, &QTimer::timeout, [this]() {
+ fitGraph();
+ if (m_rowTimeline->size().height() == m_expandHeight)
+ m_fitCurveTimer.stop();
+ });
}
void RowTimelinePropertyGraph::paintGraphs(QPainter *painter, const QRectF &rect)
{
- m_rect = rect;
m_propBinding = m_rowTimeline->rowTree()->propBinding();
- // Animate alpha 0..255 while expanding
- int alpha = 255 * (m_rect.height() - TimelineConstants::ROW_H)
- / (TimelineConstants::ROW_H_EXPANDED - TimelineConstants::ROW_H);
- alpha = std::max(0, alpha);
-
- if (alpha == 0)
+ if (rect.height() < ROW_H) // rect height = row height - 1
return;
- // Available line colors
- QColor colors[6] = { QColor(255, 0, 0, alpha), QColor(0, 255, 0, alpha),
- QColor(0, 0, 255, alpha), QColor(255, 255, 0, alpha),
- QColor(255, 0, 255, alpha), QColor(0, 255, 255, alpha) };
+ painter->setRenderHint(QPainter::Antialiasing);
+ painter->setClipRect(rect);
+
+ const QPointF edgeOffset(RULER_EDGE_OFFSET, 0);
+ double timelineScale = m_rowTimeline->rowTree()->m_scene->ruler()->timelineScale();
- long channelCount = m_propBinding->GetChannelCount();
+ // draw graph base line (graph_Y)
+ painter->setPen(QPen(CStudioPreferences::studioColor3()));
+ painter->drawLine(edgeOffset.x(), m_graphY, rect.right(), m_graphY);
- // Don't want to overflow the color array
- if (channelCount <= 6) {
- // For each channel graph it.
- for (long i = 0; i < channelCount; ++i)
- paintSingleChannel(painter, i, colors[i]);
+ // draw channel curves
+ auto animHandles = m_propBinding->animationHandles();
+ for (size_t channelIndex = 0; channelIndex < animHandles.size(); ++channelIndex) {
+ // Mahmoud_TODO: this block will draw the channel curves without sampling which is more
+ // efficient, but it cannot be used till the bezier equation is fixed (check:QT3DS-3777)
+ //-------------------------------draw using cubicTo --------------------------------------
+// QPainterPath path2;
+// Qt3DSDMTimelineKeyframe::TKeyframeHandleList keyframeHandles;
+// m_animCore->GetKeyframes(animHandles[channelIndex], keyframeHandles);
+// if (!keyframeHandles.empty()) {
+// TKeyframe kf0 = m_animCore->GetKeyframeData(keyframeHandles[0]);
+// path2.moveTo(getKeyframePosition(GetKeyframeSeconds(kf0), KeyframeValueValue(kf0))
+// + edgeOffset);
+
+// for (int i = 1; i < keyframeHandles.size(); ++i) {
+// TKeyframe kf1 = m_animCore->GetKeyframeData(keyframeHandles[i]);
+// float kf0InTime = -1, kf0InValue, kf0OutTime, kf0OutValue;
+// float kf1InTime = -1, kf1InValue, kf1OutTime, kf1OutValue;
+// getBezierValues(kf0, kf0InTime, kf0InValue, kf0OutTime, kf0OutValue);
+// getBezierValues(kf1, kf1InTime, kf1InValue, kf1OutTime, kf1OutValue);
+// if (kf0InTime != -1) {
+// path2.cubicTo(getKeyframePosition(kf0OutTime, kf0OutValue) + edgeOffset,
+// getKeyframePosition(kf1InTime, kf1InValue) + edgeOffset,
+// getKeyframePosition(GetKeyframeSeconds(kf1),
+// KeyframeValueValue(kf1))
+// + edgeOffset);
+// } else {
+// path2.lineTo(getKeyframePosition(GetKeyframeSeconds(kf1),
+// KeyframeValueValue(kf1))
+// + edgeOffset);
+// }
+// // Mahmoud_TODO: handle ease in/out curves as well
+// kf0 = kf1;
+// }
+// painter->setPen(QPen(QColor("#ff0000"), 1));
+// painter->drawPath(path2);
+// }
+ //-------------------------------draw using cubicTo --------------------------------------
+
+ QPainterPath path;
+ int start_i = qMax(rect.x(), edgeOffset.x());
+ for (int i = start_i; i < rect.right(); i += 5) { // 5 = sampling step in pixels
+ // Value time in ms
+ long time = (i - edgeOffset.x()) / (TimelineConstants::RULER_MILLI_W * timelineScale);
+ qreal value = m_propBinding->GetChannelValueAtTime(channelIndex, time);
+ qreal yPos = m_graphY - value * m_valScale;
+ if (i == start_i)
+ path.moveTo(i, yPos);
+ else
+ path.lineTo(i, yPos);
+ }
+ QColor channelColor;
+ if (channelIndex == 0)
+ channelColor = CStudioPreferences::GetXAxisColor();
+ else if (channelIndex == 1)
+ channelColor = CStudioPreferences::GetYAxisColor();
+ else if (channelIndex == 2)
+ channelColor = CStudioPreferences::GetZAxisColor();
+ painter->setPen(QPen(channelColor, 2));
+ painter->drawPath(path);
+ }
+
+ // draw bezier controls
+ if (m_rowTimeline->rowTree()->propBinding()->animationType() == EAnimationTypeBezier) {
+ static const QPixmap pixBezierHandle = QPixmap("://images/breadcrumb_component_button.png");
+ static const QPixmap pixBezierHandlePressed = QPixmap("://images/breadcrumb_component_grey"
+ "_button.png");
+
+ Qt3DSDMTimelineKeyframe::TKeyframeHandleList keyframeHandles;
+ m_animCore->GetKeyframes(animHandles[0], keyframeHandles);
+
+ size_t kfHandlesSize = keyframeHandles.size();
+ for (size_t i = 0; i < kfHandlesSize; ++i) {
+ SBezierKeyframe kf = get<SBezierKeyframe>(m_animCore->GetKeyframeData(
+ keyframeHandles[i]));
+
+ QPointF centerPos = getBezierControlPosition(kf) + edgeOffset;
+ const QPointF PIX_HALF_W = QPointF(8.0, 8.0);
+
+ // draw vertical keyframe separator line
+ painter->setPen(QPen(CStudioPreferences::studioColor2(), 1));
+ painter->drawLine(centerPos.x(), rect.y(), centerPos.x(), rect.height());
+
+ // draw tangent-in part
+ painter->setPen(CStudioPreferences::getBezierControlColor());
+ if (i > 0) {
+ QPointF cInPos = getBezierControlPosition(kf, BezierControlType::In) + edgeOffset;
+ painter->drawLine(cInPos, centerPos);
+ painter->drawPixmap(cInPos - PIX_HALF_W, pixBezierHandle);
+ }
+
+ // draw tangent-out part
+ if (i < kfHandlesSize - 1) {
+ QPointF cOutPos = getBezierControlPosition(kf, BezierControlType::Out) + edgeOffset;
+ painter->drawLine(cOutPos, centerPos);
+ painter->drawPixmap(cOutPos - PIX_HALF_W, pixBezierHandle);
+ }
+
+ // draw center point
+ painter->setPen(QPen(CStudioPreferences::getBezierControlColor(), 3));
+ painter->drawPoint(centerPos);
+ }
}
}
-void RowTimelinePropertyGraph::paintSingleChannel(QPainter *painter, long inChannelIndex,
- const QColor &inColor)
+/**
+ * This method is called when the user mouse-presses the property graph. If the press is on a
+ * bezier keyframe handle, it returns the handle type and saves the list of keyframe channels
+ * handles to be precessed while the user drags the handle (in updateBezierControlValue())
+ *
+ * @param pos press position in local coordinate system
+ * @return the pressed handle type, or None if no handle is pressed
+ */
+TimelineControlType RowTimelinePropertyGraph::getClickedBezierControl(const QPointF &pos)
{
- float maxVal = m_propBinding->GetMaximumValue();
- float minVal = m_propBinding->GetMinimumValue();
+ if (m_rowTimeline->rowTree()->propBinding()->animationType() != EAnimationTypeBezier)
+ return TimelineControlType::None;
- double timelineScale = m_rowTimeline->rowTree()->m_scene->ruler()->timelineScale();
+ m_currKeyframeHandles.clear();
+ m_currKeyframeData.clear();
+
+ auto animHandles = m_propBinding->animationHandles();
+ Qt3DSDMTimelineKeyframe::TKeyframeHandleList keyframeHandles;
+ m_animCore->GetKeyframes(animHandles[0], keyframeHandles);
+ const double CONTROL_RADIUS = 8;
+ for (auto kfHandle : keyframeHandles) {
+ SBezierKeyframe kf = get<SBezierKeyframe>(m_animCore->GetKeyframeData(kfHandle));
+
+ QPointF cInPos = getBezierControlPosition(kf, BezierControlType::In);
+ QPointF cOutPos = getBezierControlPosition(kf, BezierControlType::Out);
+ bool clickedInHandle = QLineF(cInPos, pos).length() < CONTROL_RADIUS;
+ bool clickedOutHandle = QLineF(cOutPos, pos).length() < CONTROL_RADIUS;
+ if (clickedInHandle || clickedOutHandle) {
+ m_rowTimeline->rowTree()->propBinding()->GetKeyframeByTime(kf.m_KeyframeSeconds * 1000)
+ ->getUI()->binding->GetKeyframeHandles(m_currKeyframeHandles);
+ for (auto h : m_currKeyframeHandles)
+ m_currKeyframeData.append({h, m_animCore->GetKeyframeData(h)});
+
+ return clickedInHandle ? TimelineControlType::BezierInHandle
+ : TimelineControlType::BezierOutHandle;
+ }
+ }
+
+ return TimelineControlType::None;
+}
+
+QPointF RowTimelinePropertyGraph::getBezierControlPosition(const SBezierKeyframe &kf,
+ BezierControlType type) const
+{
+ float time = 0; // seconds
+ float value = 0;
+ if (type == BezierControlType::None) {
+ time = kf.m_KeyframeSeconds;
+ value = kf.m_KeyframeValue;
+ } else if (type == BezierControlType::In) {
+ time = kf.m_InTangentTime;
+ value = kf.m_InTangentValue;
+ } else if (type == BezierControlType::Out) {
+ time = kf.m_OutTangentTime;
+ value = kf.m_OutTangentValue;
+ }
+
+ return getKeyframePosition(time, value);
+}
+
+// time is in seconds
+QPointF RowTimelinePropertyGraph::getKeyframePosition(float time, float value) const
+{
+ return QPointF(m_rowTimeline->rowTree()->m_scene->ruler()->timeToDistance(time * 1000),
+ m_graphY - value * m_valScale);
+}
+
+/**
+ * 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.
+ *
+ * @param controlType which handle is being dragged? (BezierInHandle or BezierOutHandle)
+ * @param scenePos handle position in timeline scene coordinates
+ */
+void RowTimelinePropertyGraph::updateBezierControlValue(TimelineControlType controlType,
+ const QPointF &scenePos)
+{
+ QPointF p = m_rowTimeline->mapFromScene(scenePos.x() - TimelineConstants::RULER_EDGE_OFFSET,
+ scenePos.y());
- // Step in pixels
- int interval = 5;
- // Margin at top & bottom of graph
- float marginY = 10;
- float graphY = m_rect.y() + marginY;
- float graphHeight = m_rect.height() - marginY * 2;
-
- QPainterPath path;
- for (int i = 0; i < m_rect.width(); i += interval) {
- // Value time in ms
- long time = i / (TimelineConstants::RULER_MILLI_W * timelineScale);
- float value = m_propBinding->GetChannelValueAtTime(inChannelIndex, time);
- float yPos = graphY + (1.0 - (value - minVal) / (maxVal - minVal)) * graphHeight;
-
- if (i == 0)
- path.moveTo(m_rect.x() + i, yPos);
- else
- path.lineTo(m_rect.x() + i, yPos);
+ float time = m_rowTimeline->rowTree()->m_scene->ruler()->distanceToTime(p.x()) / 1000.f; // secs
+ float value = (m_graphY - p.y()) / m_valScale;
+
+ // first channel keyframe
+ SBezierKeyframe kf0 = get<SBezierKeyframe>(m_animCore->GetKeyframeData(
+ m_currKeyframeHandles[0]));
+ bool isBezierIn = controlType == TimelineControlType::BezierInHandle;
+
+ // prevent handles from moving to the other side of the keyframe
+ if ((isBezierIn && time > kf0.m_KeyframeSeconds)
+ || (!isBezierIn && time < kf0.m_KeyframeSeconds)) {
+ time = kf0.m_KeyframeSeconds;
+ }
+
+ // prevent handles from going beyond prev. and next keyframes
+ auto animHandles = m_propBinding->animationHandles();
+ Qt3DSDMTimelineKeyframe::TKeyframeHandleList keyframeHandles;
+ m_animCore->GetKeyframes(animHandles[0], keyframeHandles);
+ for (size_t i = 0; i < keyframeHandles.size(); ++i) {
+ if (keyframeHandles[i] == m_currKeyframeHandles[0]) {
+ float currKfTime = KeyframeTime(m_animCore->GetKeyframeData(keyframeHandles[i]));
+ float prevKfTime = i > 0
+ ? KeyframeTime(m_animCore->GetKeyframeData(keyframeHandles[i - 1])) : -FLT_MAX;
+ float nextKfTime = i < keyframeHandles.size() - 1
+ ? KeyframeTime(m_animCore->GetKeyframeData(keyframeHandles[i + 1])) : FLT_MAX;
+ if (isBezierIn) {
+ if (time < prevKfTime)
+ time = prevKfTime;
+ if (!CHotKeys::IsKeyDown(Qt::ControlModifier)
+ && time < currKfTime * 2 - nextKfTime) {
+ time = currKfTime * 2 - nextKfTime;
+ }
+ } else { // bezier out
+ if (time > nextKfTime)
+ time = nextKfTime;
+ if (!CHotKeys::IsKeyDown(Qt::ControlModifier)
+ && time > currKfTime * 2 - prevKfTime) {
+ time = currKfTime * 2 - prevKfTime;
+ }
+ }
+ break;
+ }
+ }
+
+ for (size_t i = 0; i < m_currKeyframeHandles.size(); ++i) {
+ SBezierKeyframe kf = get<SBezierKeyframe>(m_animCore->GetKeyframeData(
+ m_currKeyframeHandles[i]));
+ float &currHandleTime = isBezierIn ? kf.m_InTangentTime : kf.m_OutTangentTime;
+ float &currHandleValue = isBezierIn ? kf.m_InTangentValue : kf.m_OutTangentValue;
+ float &otherHandleTime = isBezierIn ? kf.m_OutTangentTime : kf.m_InTangentTime;
+ float &otherHandleValue = isBezierIn ? kf.m_OutTangentValue : kf.m_InTangentValue;
+
+ currHandleTime = time;
+ currHandleValue = value + (kf.m_KeyframeValue - kf0.m_KeyframeValue);
+
+ if (!CHotKeys::IsKeyDown(Qt::ControlModifier)) {
+ otherHandleTime = kf.m_KeyframeSeconds + (kf.m_KeyframeSeconds - time);
+ otherHandleValue = kf.m_KeyframeValue + (kf.m_KeyframeValue - currHandleValue);
+ }
+
+ m_animCore->SetKeyframeData(m_currKeyframeHandles[i], kf);
}
- painter->setPen(QPen(inColor, 2));
- painter->drawPath(path);
+}
+
+// adjust graph scale and y so that all keyframe and control points are visible
+void RowTimelinePropertyGraph::fitGraph()
+{
+ const qreal MARGIN_Y = 10; // margin at top & bottom of graph
+ m_graphY = m_rowTimeline->size().height() - MARGIN_Y;
+ m_graphH = m_rowTimeline->size().height() - MARGIN_Y * 2;
+
+ m_valScale = m_graphH / (m_propBinding->GetMaximumValue() - m_propBinding->GetMinimumValue());
+ m_graphY += m_propBinding->GetMinimumValue() * m_valScale;
+
+ m_rowTimeline->update();
+}
+
+void RowTimelinePropertyGraph::adjustScale(bool isIncrement)
+{
+ float pitch = m_valScale * .3f;
+ m_valScale += isIncrement ? pitch : -pitch;
+
+ if (m_valScale > 10.f)
+ m_valScale = 10.f;
+ else if (m_valScale < .01f)
+ m_valScale = .01f;
+
+ m_rowTimeline->update();
+}
+
+void RowTimelinePropertyGraph::startPan()
+{
+ m_graphYPanInit = m_graphY;
+}
+
+void RowTimelinePropertyGraph::pan(qreal dy)
+{
+ m_graphY = m_graphYPanInit + dy;
+ m_rowTimeline->update();
+}
+
+void RowTimelinePropertyGraph::commitBezierEdit()
+{
+ // reset the changed keyframes and commit the changes, so the undo/redo works correctly
+ QVector<std::pair<qt3dsdm::Qt3DSDMKeyframeHandle, TKeyframe>> changedKfs;
+ for (auto data : qAsConst(m_currKeyframeData)) {
+ changedKfs.append({data.first, m_animCore->GetKeyframeData(data.first)});
+ m_animCore->SetKeyframeData(data.first, data.second);
+ }
+
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*g_StudioApp.GetCore()->GetDoc(), tr("Edit Bezier curve"))
+ ->setBezierKeyframeValues(changedKfs);
+}
+
+void RowTimelinePropertyGraph::setExpandHeight(int h)
+{
+ m_expandHeight = h;
+ m_fitCurveTimer.start();
}
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.h
index 275c24e2..5c3f1a71 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.h
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.h
@@ -29,26 +29,56 @@
#ifndef ROWTIMELINEPROPERTYGRAPH_H
#define ROWTIMELINEPROPERTYGRAPH_H
+#include "Qt3DSDMAnimation.h"
+#include "RowTypes.h"
+#include "TimelineConstants.h"
+#include "Bindings/Qt3DSDMTimelineKeyframe.h"
+
#include <QtCore/qobject.h>
+#include <QtCore/qtimer.h>
#include <QtGui/qpainter.h>
class RowTimeline;
class ITimelineItemProperty;
+namespace qt3dsdm {
+class IAnimationCore;
+class Qt3DSDMAnimationHandle;
+}
class RowTimelinePropertyGraph : public QObject
{
Q_OBJECT
+
public:
explicit RowTimelinePropertyGraph(QObject *parent = nullptr);
+ TimelineControlType getClickedBezierControl(const QPointF &pos);
void paintGraphs(QPainter *painter, const QRectF &rect);
+ void updateBezierControlValue(TimelineControlType controlType, const QPointF &scenePos);
+ void adjustScale(bool isIncrement);
+ void startPan();
+ void pan(qreal dy);
+ void fitGraph();
+ void commitBezierEdit();
+ void setExpandHeight(int h);
private:
- void paintSingleChannel(QPainter *painter, long inChannelIndex,
- const QColor &inColor);
+ enum class BezierControlType {None, In, Out};
+
+ QPointF getBezierControlPosition(const qt3dsdm::SBezierKeyframe &kf,
+ BezierControlType type = BezierControlType::None) const;
+ QPointF getKeyframePosition(float time, float value) const;
+ Qt3DSDMTimelineKeyframe::TKeyframeHandleList m_currKeyframeHandles;
+ QVector<std::pair<qt3dsdm::Qt3DSDMKeyframeHandle, qt3dsdm::TKeyframe>> m_currKeyframeData;
RowTimeline *m_rowTimeline = nullptr;
ITimelineItemProperty *m_propBinding = nullptr;
- QRectF m_rect;
+ qt3dsdm::IAnimationCore *m_animCore = nullptr;
+ float m_valScale = .5f;
+ qreal m_graphY = 0;
+ qreal m_graphYPanInit = 0; // value of graph_y when panning starts
+ qreal m_graphH = 0;
+ int m_expandHeight = TimelineConstants::ROW_GRAPH_H; // height when expanded
+ QTimer m_fitCurveTimer;
};
#endif // ROWTIMELINEPROPERTYGRAPH_H
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.cpp
index e15258cd..9dace42b 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.cpp
@@ -28,6 +28,7 @@
#include "RowTree.h"
#include "RowTimeline.h"
+#include "RowTimelinePropertyGraph.h"
#include "RowManager.h"
#include "TimelineConstants.h"
#include "StudioObjectTypes.h"
@@ -169,8 +170,7 @@ void RowTree::animateExpand(ExpandState state)
int endHeight = 0; // hidden states
float endOpacity = 0;
if (state == ExpandState::Expanded) {
- endHeight = m_isPropertyExpanded ? TimelineConstants::ROW_H_EXPANDED
- : TimelineConstants::ROW_H;
+ endHeight = m_propGraphExpanded ? m_propGraphHeight : TimelineConstants::ROW_H;
endOpacity = 1;
} else if (state == ExpandState::Collapsed) {
endHeight = TimelineConstants::ROW_H;
@@ -179,7 +179,6 @@ void RowTree::animateExpand(ExpandState state)
// Changing end values while animation is running does not affect currently running animation,
// so let's make sure the animation is stopped first.
m_expandAnimation.stop();
-
m_expandHeightAnimation->setEndValue(QSizeF(size().width(), endHeight));
m_expandTimelineHeightAnimation->setEndValue(QSizeF(m_rowTimeline->size().width(),
endHeight));
@@ -201,15 +200,15 @@ void RowTree::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q
static const int ICON_SIZE = 16;
static const int LEFT_DIVIDER = 18;
+ static const int ICON_Y = (TimelineConstants::ROW_H - ICON_SIZE) / 2;
const int offset = 5 + m_depth * TimelineConstants::ROW_DEPTH_STEP;
- const int iconY = (TimelineConstants::ROW_H / 2) - (ICON_SIZE / 2);
// update button bounds rects
- m_rectArrow .setRect(offset, iconY, ICON_SIZE, ICON_SIZE);
- m_rectType .setRect(offset + ICON_SIZE, iconY, ICON_SIZE, ICON_SIZE);
- m_rectShy .setRect(treeWidth() - 16 * 3.3, iconY, ICON_SIZE, ICON_SIZE);
- m_rectVisible.setRect(treeWidth() - 16 * 2.2, iconY, ICON_SIZE, ICON_SIZE);
- m_rectLocked .setRect(treeWidth() - 16 * 1.1, iconY, ICON_SIZE, ICON_SIZE);
+ m_rectArrow .setRect(offset, ICON_Y, ICON_SIZE, ICON_SIZE);
+ m_rectType .setRect(offset + ICON_SIZE, ICON_Y, ICON_SIZE, ICON_SIZE);
+ m_rectShy .setRect(treeWidth() - 16 * 3.3, ICON_Y, ICON_SIZE, ICON_SIZE);
+ m_rectVisible.setRect(treeWidth() - 16 * 2.2, ICON_Y, ICON_SIZE, ICON_SIZE);
+ m_rectLocked .setRect(treeWidth() - 16 * 1.1, ICON_Y, ICON_SIZE, ICON_SIZE);
// Background
QColor bgColor;
@@ -235,8 +234,7 @@ void RowTree::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q
painter->drawLine(LEFT_DIVIDER, 0, LEFT_DIVIDER, size().height() - 1);
// Shy, eye, lock separator
- painter->fillRect(QRect(treeWidth() - TimelineConstants::TREE_ICONS_W,
- 0, 1, size().height()),
+ painter->fillRect(QRect(rightDividerX(), 0, 1, size().height()),
CStudioPreferences::timelineWidgetBgColor());
// Shy, eye, lock
@@ -280,8 +278,7 @@ void RowTree::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q
static const QPixmap pixInsertRight2x = QPixmap(":/images/Insert-Right@2x.png");
if (m_dndState == DnDState::SP_TARGET) { // Candidate target of a subpresentation drop
painter->drawPixmap(19, 2, hiResIcons ? pixInsertLeft2x : pixInsertLeft);
- painter->drawPixmap(treeWidth() - TimelineConstants::TREE_ICONS_W - 8, 2, hiResIcons
- ? pixInsertRight2x : pixInsertRight);
+ painter->drawPixmap(rightDividerX() - 8, 2, hiResIcons ? pixInsertRight2x : pixInsertRight);
} else if (m_dndState == DnDState::Parent) { // Candidate parent of a dragged row
painter->setPen(QPen(CStudioPreferences::timelineRowMoverColor(), 1));
painter->drawRect(QRect(1, 1, treeWidth() - 2, size().height() - 3));
@@ -333,6 +330,17 @@ void RowTree::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q
painter->drawPixmap(0, 0, hiResIcons ? pixCompMasterAction2x : pixCompMasterAction);
else if (m_actionStates & ActionState::ComponentAction) // component has action
painter->drawPixmap(0, 0, hiResIcons ? pixCompAction2x : pixCompAction);
+ } else { // property row
+ if (m_propGraphExpanded
+ && m_PropBinding->animationType() == qt3dsdm::EAnimationTypeBezier) {
+ const int PROP_GRAPH_CONTROLS_Y = int(TimelineConstants::ROW_H * 1.5);
+ m_rectMaximizePropGraph.setRect(rightDividerX() - 16 * 1.1, PROP_GRAPH_CONTROLS_Y,
+ ICON_SIZE, ICON_SIZE);
+ m_rectFitPropGraph.setRect(rightDividerX() - 16 * 2.2, PROP_GRAPH_CONTROLS_Y,
+ ICON_SIZE, ICON_SIZE);
+ painter->drawPixmap(m_rectMaximizePropGraph, pixShy);
+ painter->drawPixmap(m_rectFitPropGraph, pixShy);
+ }
}
// variants indicator
@@ -541,7 +549,12 @@ void RowTree::setBinding(ITimelineItemBinding *binding)
// x value where label should clip
int RowTree::clipX() const
{
- return treeWidth() - TimelineConstants::TREE_ICONS_W - m_variantsGroups.size() * 8 - 2;
+ return rightDividerX() - m_variantsGroups.size() * 8 - 2;
+}
+
+int RowTree::rightDividerX() const
+{
+ return treeWidth() - TimelineConstants::TREE_ICONS_W;
}
ITimelineItemProperty *RowTree::propBinding()
@@ -947,8 +960,7 @@ bool RowTree::hasPropertyChildren() const
void RowTree::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
- QPointF p = event->pos();
- if (m_rectType.contains(p.x(), p.y()) && !m_locked)
+ if (m_rectType.contains(event->pos().toPoint()) && !m_locked)
if (m_binding)
m_binding->OpenAssociatedEditor();
}
@@ -956,8 +968,8 @@ void RowTree::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
// handle clicked control and return its type
TreeControlType RowTree::getClickedControl(const QPointF &scenePos)
{
- QPointF p = mapFromScene(scenePos.x(), scenePos.y());
- if (m_arrowVisible && m_rectArrow.contains(p.x(), p.y())) {
+ QPoint p = mapFromScene(scenePos).toPoint();
+ if (m_arrowVisible && m_rectArrow.contains(p)) {
updateExpandStatus(m_expandState == ExpandState::Expanded ? ExpandState::Collapsed
: ExpandState::Expanded, false);
update();
@@ -965,19 +977,30 @@ TreeControlType RowTree::getClickedControl(const QPointF &scenePos)
}
if (hasActionButtons()) {
- if (m_rectShy.contains(p.x(), p.y())) {
+ if (m_rectShy.contains(p)) {
toggleShy();
return TreeControlType::Shy;
- } else if (!m_onMasterSlide && m_rectVisible.contains(p.x(), p.y())) {
+ } else if (!m_onMasterSlide && m_rectVisible.contains(p)) {
// Prevent toggling hide on master slide
toggleVisible();
return TreeControlType::Hide;
- } else if (m_rectLocked.contains(p.x(), p.y())) {
+ } else if (m_rectLocked.contains(p)) {
toggleLocked();
return TreeControlType::Lock;
}
}
+ if (isProperty()) {
+ if (m_rectFitPropGraph.contains(p)) {
+ m_rowTimeline->propertyGraph()->fitGraph();
+ } else if (m_rectMaximizePropGraph.contains(p)) {
+ m_propGraphHeight = m_propGraphHeight == TimelineConstants::ROW_GRAPH_H
+ ? TimelineConstants::ROW_GRAPH_H_MAX : TimelineConstants::ROW_GRAPH_H;
+ m_rowTimeline->propertyGraph()->setExpandHeight(m_propGraphHeight);
+ animateExpand(ExpandState::Expanded);
+ }
+ }
+
return TreeControlType::None;
}
@@ -1306,21 +1329,33 @@ bool RowTree::hasDurationBar() const
bool RowTree::propertyExpanded() const
{
- return m_isPropertyExpanded;
+ return m_propGraphExpanded;
}
-void RowTree::togglePropertyExpanded()
+/**
+ * toggle property graph if the mouse isn't over other buttons
+ *
+ * @param scenePos mouse position in graphics scene coordinates
+ */
+void RowTree::togglePropertyExpanded(const QPointF &scenePos)
{
- setPropertyExpanded(!m_isPropertyExpanded);
+ QPoint p = mapFromScene(scenePos).toPoint();
+ if (!m_rectFitPropGraph.contains(p) && !m_rectMaximizePropGraph.contains(p))
+ setPropertyExpanded(!m_propGraphExpanded);
}
void RowTree::setPropertyExpanded(bool expand)
{
- m_isPropertyExpanded = expand;
- if (m_isPropertyExpanded)
+ m_propGraphExpanded = expand;
+ if (m_propGraphExpanded) {
+ // start graph in normal (not maximized) size
+ m_propGraphHeight = TimelineConstants::ROW_GRAPH_H;
+ m_rowTimeline->propertyGraph()->setExpandHeight(m_propGraphHeight);
+ m_rowTimeline->propertyGraph()->fitGraph();
animateExpand(ExpandState::Expanded);
- else
+ } else {
animateExpand(ExpandState::Collapsed);
+ }
}
void RowTree::showDataInputSelector(const QString &propertyname, const QPoint &pos)
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.h
index b028e94d..75afcaf0 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.h
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.h
@@ -97,7 +97,7 @@ public:
void setBinding(ITimelineItemBinding *binding);
void setPropBinding(ITimelineItemProperty *binding); // for property rows
void selectLabel();
- void togglePropertyExpanded();
+ void togglePropertyExpanded(const QPointF &scenePos = {});
void setPropertyExpanded(bool expand);
void showDataInputSelector(const QString &propertyname, const QPoint &pos);
ITimelineItemProperty *propBinding();
@@ -152,6 +152,7 @@ public:
void updateFilter();
void updateLock(bool state);
void updateSubpresentations(int updateParentsOnlyVal = 0);
+ int rightDividerX() const;
int clipX() const;
qt3dsdm::Qt3DSDMInstanceHandle instance() const;
@@ -183,7 +184,8 @@ private:
bool m_visible = true;
bool m_locked = false;
bool m_isProperty = false;
- bool m_isPropertyExpanded = false;
+ bool m_propGraphExpanded = false;
+ int m_propGraphHeight = TimelineConstants::ROW_GRAPH_H;
bool m_master = false;
bool m_filtered = false;
bool m_arrowVisible = false;
@@ -211,6 +213,8 @@ private:
QRect m_rectVisible;
QRect m_rectLocked;
QRect m_rectType;
+ QRect m_rectMaximizePropGraph;
+ QRect m_rectFitPropGraph;
QParallelAnimationGroup m_expandAnimation;
QPropertyAnimation *m_expandHeightAnimation;
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/TimelineItem.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/TimelineItem.cpp
index 866d8109..205158e1 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/TimelineItem.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/TimelineItem.cpp
@@ -33,7 +33,7 @@
TimelineItem::TimelineItem(TimelineItem *parent) : QGraphicsWidget(parent)
{
- setPreferredHeight(TimelineConstants::ROW_H_EXPANDED);
+ setPreferredHeight(TimelineConstants::ROW_GRAPH_H_MAX);
setMaximumHeight(TimelineConstants::ROW_H);
}
diff --git a/src/Authoring/Qt3DStudio/UI/InterpolationDlg.cpp b/src/Authoring/Qt3DStudio/UI/InterpolationDlg.cpp
index 9c4c5c38..be69bed6 100644
--- a/src/Authoring/Qt3DStudio/UI/InterpolationDlg.cpp
+++ b/src/Authoring/Qt3DStudio/UI/InterpolationDlg.cpp
@@ -27,22 +27,18 @@
**
****************************************************************************/
-#include "Qt3DSCommonPrecompile.h"
#include "InterpolationDlg.h"
#include "ui_InterpolationDlg.h"
-/**
- * Constructor: Creates a CInterpolationDlg.
- *
- * @param parent Pointer to the parent of this dialog (defaults to NULL)
- */
-//==============================================================================
-CInterpolationDlg::CInterpolationDlg(QWidget *parent)
+CInterpolationDlg::CInterpolationDlg(float easeIn, float easeOut, QWidget *parent)
: QDialog(parent)
, m_ui(new Ui::InterpolationDlg)
{
m_ui->setupUi(this);
window()->setFixedSize(size());
+
+ m_ui->easeInSlider->setValue(int(easeIn));
+ m_ui->easeOutSlider->setValue(int(easeOut));
}
CInterpolationDlg::~CInterpolationDlg()
@@ -51,22 +47,13 @@ CInterpolationDlg::~CInterpolationDlg()
m_ui = nullptr;
}
-void CInterpolationDlg::setEaseIn(uint value)
-{
- m_ui->easeInSlider->setValue(value);
-}
-
-void CInterpolationDlg::setEaseOut(uint value)
-{
- m_ui->easeOutSlider->setValue(value);
-}
-int CInterpolationDlg::easeIn() const
+float CInterpolationDlg::easeIn() const
{
return m_ui->easeInSlider->value();
}
-int CInterpolationDlg::easeOut() const
+float CInterpolationDlg::easeOut() const
{
return m_ui->easeOutSlider->value();
}
diff --git a/src/Authoring/Qt3DStudio/UI/InterpolationDlg.h b/src/Authoring/Qt3DStudio/UI/InterpolationDlg.h
index 0b324bd3..ebff86de 100644
--- a/src/Authoring/Qt3DStudio/UI/InterpolationDlg.h
+++ b/src/Authoring/Qt3DStudio/UI/InterpolationDlg.h
@@ -27,16 +27,10 @@
**
****************************************************************************/
-//==============================================================================
-// Prefix
-//==============================================================================
-
#ifndef INCLUDED_INTERPOLATION_DLG
-#define INCLUDED_INTERPOLATION_DLG 1
-
-#pragma once
+#define INCLUDED_INTERPOLATION_DLG
-#include <QDialog>
+#include <QtWidgets/qdialog.h>
QT_BEGIN_NAMESPACE
namespace Ui {
@@ -44,22 +38,19 @@ class InterpolationDlg;
}
QT_END_NAMESPACE
-//==============================================================================
/**
- * CInterpolationDlg: Dialog class for editing the ease-in/ease-out values of keyframes.
+ * CInterpolationDlg: Dialog class for editing keyframes interpolation
*/
-//==============================================================================
class CInterpolationDlg : public QDialog
{
Q_OBJECT
+
public:
- explicit CInterpolationDlg(QWidget *parent = nullptr); // standard constructor
+ explicit CInterpolationDlg(float easeIn, float easeOut, QWidget *parent = nullptr);
~CInterpolationDlg();
- void setEaseIn(uint value);
- void setEaseOut(uint value);
- int easeIn() const;
- int easeOut() const;
+ float easeIn() const;
+ float easeOut() const;
protected:
QT_PREPEND_NAMESPACE(Ui::InterpolationDlg) *m_ui = nullptr;
diff --git a/src/Authoring/Qt3DStudio/UI/InterpolationDlg.ui b/src/Authoring/Qt3DStudio/UI/InterpolationDlg.ui
index 0d27d777..710fee6b 100644
--- a/src/Authoring/Qt3DStudio/UI/InterpolationDlg.ui
+++ b/src/Authoring/Qt3DStudio/UI/InterpolationDlg.ui
@@ -1,311 +1,316 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
- <class>InterpolationDlg</class>
- <widget class="QDialog" name="InterpolationDlg">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>425</width>
- <height>195</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Set Keyframe Interpolation</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QGridLayout" name="gridLayout">
- <item row="2" column="1" colspan="2">
- <widget class="QSlider" name="easeOutSlider">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="maximum">
- <number>100</number>
- </property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="tickPosition">
- <enum>QSlider::TicksBelow</enum>
- </property>
- <property name="tickInterval">
- <number>10</number>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Ease In:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QLabel" name="label_4">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Smooth</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="0" column="1" colspan="2">
- <widget class="QSlider" name="easeInSlider">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="maximum">
- <number>100</number>
- </property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="tickPosition">
- <enum>QSlider::TicksBelow</enum>
- </property>
- <property name="tickInterval">
- <number>10</number>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLabel" name="label_3">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Linear</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QLabel" name="label_5">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Linear</string>
- </property>
- </widget>
- </item>
- <item row="3" column="2">
- <widget class="QLabel" name="label_6">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Smooth</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_2">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Ease Out:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="3">
- <widget class="QSpinBox" name="easeInSpinBox">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="maximum">
- <number>100</number>
- </property>
- </widget>
- </item>
- <item row="2" column="3">
- <widget class="QSpinBox" name="easeOutSpinBox">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="maximum">
- <number>100</number>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <tabstops>
- <tabstop>easeInSlider</tabstop>
- <tabstop>easeInSpinBox</tabstop>
- <tabstop>easeOutSlider</tabstop>
- <tabstop>easeOutSpinBox</tabstop>
- </tabstops>
- <resources/>
- <connections>
- <connection>
- <sender>buttonBox</sender>
- <signal>accepted()</signal>
- <receiver>InterpolationDlg</receiver>
- <slot>accept()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>224</x>
- <y>272</y>
- </hint>
- <hint type="destinationlabel">
- <x>157</x>
- <y>274</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>buttonBox</sender>
- <signal>rejected()</signal>
- <receiver>InterpolationDlg</receiver>
- <slot>reject()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>316</x>
- <y>260</y>
- </hint>
- <hint type="destinationlabel">
- <x>286</x>
- <y>274</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>easeInSlider</sender>
- <signal>valueChanged(int)</signal>
- <receiver>easeInSpinBox</receiver>
- <slot>setValue(int)</slot>
- <hints>
- <hint type="sourcelabel">
- <x>331</x>
- <y>21</y>
- </hint>
- <hint type="destinationlabel">
- <x>542</x>
- <y>35</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>easeOutSlider</sender>
- <signal>valueChanged(int)</signal>
- <receiver>easeOutSpinBox</receiver>
- <slot>setValue(int)</slot>
- <hints>
- <hint type="sourcelabel">
- <x>210</x>
- <y>93</y>
- </hint>
- <hint type="destinationlabel">
- <x>545</x>
- <y>93</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>easeInSpinBox</sender>
- <signal>valueChanged(int)</signal>
- <receiver>easeInSlider</receiver>
- <slot>setValue(int)</slot>
- <hints>
- <hint type="sourcelabel">
- <x>533</x>
- <y>24</y>
- </hint>
- <hint type="destinationlabel">
- <x>408</x>
- <y>18</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>easeOutSpinBox</sender>
- <signal>valueChanged(int)</signal>
- <receiver>easeOutSlider</receiver>
- <slot>setValue(int)</slot>
- <hints>
- <hint type="sourcelabel">
- <x>546</x>
- <y>98</y>
- </hint>
- <hint type="destinationlabel">
- <x>338</x>
- <y>84</y>
- </hint>
- </hints>
- </connection>
- </connections>
+ <class>InterpolationDlg</class>
+ <widget class="QDialog" name="InterpolationDlg">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>425</width>
+ <height>195</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Set Keyframe Interpolation</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="1" column="0">
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Ease In:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" colspan="2">
+ <widget class="QSlider" name="easeInSlider">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QSpinBox" name="easeInSpinBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="label_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Linear</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QLabel" name="label_4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Smooth</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Ease Out:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" colspan="2">
+ <widget class="QSlider" name="easeOutSlider">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="3">
+ <widget class="QSpinBox" name="easeOutSpinBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QLabel" name="label_5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Linear</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2">
+ <widget class="QLabel" name="label_6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Smooth</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>easeInSlider</tabstop>
+ <tabstop>easeInSpinBox</tabstop>
+ <tabstop>easeOutSlider</tabstop>
+ <tabstop>easeOutSpinBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>InterpolationDlg</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>233</x>
+ <y>211</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>InterpolationDlg</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>325</x>
+ <y>211</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>easeInSlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>easeInSpinBox</receiver>
+ <slot>setValue(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>108</x>
+ <y>58</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>406</x>
+ <y>72</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>easeOutSlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>easeOutSpinBox</receiver>
+ <slot>setValue(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>171</x>
+ <y>136</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>406</x>
+ <y>132</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>easeInSpinBox</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>easeInSlider</receiver>
+ <slot>setValue(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>406</x>
+ <y>72</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>108</x>
+ <y>55</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>easeOutSpinBox</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>easeOutSlider</receiver>
+ <slot>setValue(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>406</x>
+ <y>132</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>171</x>
+ <y>136</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
</ui>
diff --git a/src/Authoring/Qt3DStudio/Workspace/Dialogs.cpp b/src/Authoring/Qt3DStudio/Workspace/Dialogs.cpp
index 2a5a6780..5ba8abe6 100644
--- a/src/Authoring/Qt3DStudio/Workspace/Dialogs.cpp
+++ b/src/Authoring/Qt3DStudio/Workspace/Dialogs.cpp
@@ -229,27 +229,21 @@ CDialogs::~CDialogs()
*
* @param ioEaseIn value to be set as the ease in default - passes back the value chosen by the user
* @param ioEaseOut value to be set as the ease out default - passes back the value chosen by the
- * user
* @return true if the user clicked OK on the dialog (indicating that the values should be updated
* on the track)
*/
-bool CDialogs::PromptForKeyframeInterpolation(float &ioEaseIn, float &ioEaseOut)
+bool CDialogs::displayKeyframeInterpolation(float &ioEaseIn, float &ioEaseOut)
{
- bool theReturnValue = false;
+ CInterpolationDlg interpolationDialog(ioEaseIn, ioEaseOut);
- CInterpolationDlg theInterpolationDialog;
- theInterpolationDialog.setEaseIn(ioEaseIn);
- theInterpolationDialog.setEaseOut(ioEaseOut);
-
- // If the user presses the OK button
- if (theInterpolationDialog.exec() == QDialog::Accepted) {
+ if (interpolationDialog.exec() == QDialog::Accepted) {
// Retrieve the new interpolation values
- ioEaseIn = theInterpolationDialog.easeIn();
- ioEaseOut = theInterpolationDialog.easeOut();
- theReturnValue = true;
+ ioEaseIn = interpolationDialog.easeIn();
+ ioEaseOut = interpolationDialog.easeOut();
+ return true;
}
- return theReturnValue;
+ return false;
}
/**
diff --git a/src/Authoring/Qt3DStudio/Workspace/Dialogs.h b/src/Authoring/Qt3DStudio/Workspace/Dialogs.h
index 02f0b8d3..b10922cb 100644
--- a/src/Authoring/Qt3DStudio/Workspace/Dialogs.h
+++ b/src/Authoring/Qt3DStudio/Workspace/Dialogs.h
@@ -145,7 +145,7 @@ public:
QColor displayColorDialog(const QColor &color, bool showAlpha = false) const;
ESavePromptResult PromptForSave();
- bool PromptForKeyframeInterpolation(float &ioEaseIn, float &ioEaseOut);
+ bool displayKeyframeInterpolation(float &ioEaseIn, float &ioEaseOut);
bool ConfirmRevert();
diff --git a/src/Runtime/ogl-runtime b/src/Runtime/ogl-runtime
-Subproject e13ab913d2fe4d1b8d687713693b5a8bb5856e7
+Subproject 3bcd2a4e81ffced186b060de8eee905b5c65f78