1f9b284de2
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> # Conflicts: # Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h # Code/Editor/Plugins/EditorCommon/EditorCommon_precompiled.h # Code/Editor/Plugins/EditorCommon/stdafx.cpp # Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin_precompiled.h # Code/Editor/Plugins/PerforcePlugin/PerforcePlugin_precompiled.h # Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsTool_precompiled.h # Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFramework_precompiled.h # Code/Tools/AssetProcessor/native/precompiled.h # Code/Tools/Standalone/StandaloneTools_precompiled.h # Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer_precompiled.h # Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageProcessing_precompiled.h # Gems/Atom/RHI/DX12/Code/Source/RHI/Atom_RHI_DX12_precompiled.h # Gems/Atom/RHI/Metal/Code/Include/Platform/Mac/Atom_RHI_Metal_precompiled_Platform.h # Gems/Atom/RHI/Metal/Code/Include/Platform/iOS/Atom_RHI_Metal_precompiled_Platform.h # Gems/Atom/RHI/Metal/Code/Source/Atom_RHI_Metal_precompiled.h # Gems/Atom/RHI/Metal/Code/atom_rhi_metal_common_files.cmake # Gems/Atom/RHI/Null/Code/Source/Atom_RHI_Null_precompiled.h # Gems/Atom/RHI/Null/Code/atom_rhi_null_common_files.cmake # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Android/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Linux/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Mac/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Windows/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Source/Atom_RHI_Vulkan_precompiled.h # Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp # Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_common_files.cmake # Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h # Gems/Blast/Code/Source/StdAfx.cpp # Gems/Camera/Code/Source/Camera_precompiled.h # Gems/EMotionFX/Code/Source/EMotionFX_precompiled.h # Gems/FastNoise/Code/Source/FastNoise_precompiled.h # Gems/Gestures/Code/Source/Gestures_precompiled.h # Gems/GradientSignal/Code/Source/GradientSignal_precompiled.h # Gems/GraphCanvas/Code/precompiled.h # Gems/ImGui/Code/Source/ImGui_precompiled.h # Gems/InAppPurchases/Code/Source/InAppPurchases_precompiled.h # Gems/LmbrCentral/Code/Source/LmbrCentral_precompiled.h # Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp # Gems/LyShine/Code/Editor/UiCanvasEditor_precompiled.h # Gems/LyShine/Code/Source/Animation/LyShine_precompiled.h # Gems/LyShine/Code/Source/LyShine_precompiled.h # Gems/LyShineExamples/Code/Source/LyShineExamples_precompiled.h # Gems/Maestro/Code/Source/Cinematics/Maestro_precompiled.h # Gems/Maestro/Code/Source/Maestro_precompiled.h # Gems/MessagePopup/Code/Source/MessagePopup_precompiled.h # Gems/Metastream/Code/Source/Metastream_precompiled.h # Gems/Microphone/Code/Source/Microphone_precompiled.h # Gems/Multiplayer/Code/Source/Multiplayer_precompiled.h # Gems/PhysX/Code/NumericalMethods/Source/NumericalMethods_precompiled.h # Gems/PhysX/Code/Source/PhysXUnsupported_precompiled.h # Gems/PhysX/Code/Source/PhysX_precompiled.h # Gems/PhysX/Code/physx_unsupported_files.cmake # Gems/PhysXDebug/Code/Source/PhysXDebugUnsupported_precompiled.h # Gems/PhysXDebug/Code/Source/PhysXDebug_precompiled.h # Gems/ScriptCanvas/Code/Editor/precompiled.h # Gems/ScriptCanvas/Code/Source/precompiled.h # Gems/ScriptCanvasDeveloper/Code/Source/precompiled.h # Gems/ScriptCanvasPhysics/Code/Source/ScriptCanvasPhysics_precompiled.h # Gems/ScriptEvents/Code/Source/precompiled.h # Gems/ScriptEvents/Code/Tests/Editor/EditorTests.cpp # Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweener_precompiled.h # Gems/SliceFavorites/Code/Source/SliceFavorites_precompiled.h # Gems/StartingPointCamera/Code/Source/StartingPointCamera_precompiled.h # Gems/StartingPointInput/Code/Source/StartingPointInput_precompiled.h # Gems/StartingPointMovement/Code/Source/StartingPointMovement_precompiled.h # Gems/SurfaceData/Code/Source/SurfaceData_precompiled.h # Gems/TextureAtlas/Code/Source/TextureAtlas_precompiled.h # Gems/TickBusOrderViewer/Code/Source/TickBusOrderViewer_precompiled.h # Gems/Twitch/Code/Source/Twitch_precompiled.h # Gems/VirtualGamepad/Code/Source/VirtualGamepad_precompiled.h # Gems/WhiteBox/Code/Source/WhiteBoxUnsupported_precompiled.h # Gems/WhiteBox/Code/Source/WhiteBox_precompiled.h
673 lines
18 KiB
C++
673 lines
18 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
|
|
#include <Animation/Controls/UiTimelineCtrl.h>
|
|
#include "EditorDefs.h"
|
|
//#include "MemDC.h"
|
|
#include "ScopedVariableSetter.h"
|
|
#include "../GridUtils.h"
|
|
|
|
#include <QKeyEvent>
|
|
#include <QMouseEvent>
|
|
#include <QPainter>
|
|
#include <QStaticText>
|
|
|
|
QColor InterpolateColor(const QColor& c1, const QColor& c2, float fraction)
|
|
{
|
|
const int r = (c2.red() - c1.red()) * fraction + c1.red();
|
|
const int g = (c2.green() - c1.green()) * fraction + c1.green();
|
|
const int b = (c2.blue() - c1.blue()) * fraction + c1.blue();
|
|
return QColor(r, g, b);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
TimelineWidget::TimelineWidget()
|
|
{
|
|
setMouseTracking(true);
|
|
|
|
m_timeRange.start = 0;
|
|
m_timeRange.end = 1;
|
|
|
|
m_timeScale = 1;
|
|
m_fTicksTextScale = 1.0f;
|
|
|
|
m_fTimeMarker = -10;
|
|
|
|
m_nTicksStep = 100;
|
|
|
|
m_trackingMode = TRACKING_MODE_NONE;
|
|
|
|
m_leftOffset = 0;
|
|
m_scrollOffset = 0;
|
|
|
|
m_ticksStep = 10.0f;
|
|
|
|
m_grid.zoom.x = 100;
|
|
|
|
m_bIgnoreSetTime = false;
|
|
|
|
m_pKeyTimeSet = 0;
|
|
|
|
m_markerStyle = MARKER_STYLE_SECONDS;
|
|
m_fps = 30.0f;
|
|
|
|
m_copyKeyTimes = false;
|
|
m_bTrackingSnapToFrames = false;
|
|
}
|
|
|
|
TimelineWidget::~TimelineWidget()
|
|
{
|
|
}
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CTimelineCtrl message handlers
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::resizeEvent(QResizeEvent* event)
|
|
{
|
|
Q_UNUSED(event);
|
|
m_rcTimeline = rect();
|
|
m_grid.rect = m_rcTimeline;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
int TimelineWidget::TimeToClient(float time)
|
|
{
|
|
return m_grid.WorldToClient(Vec2(time, 0)).x();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
float TimelineWidget::ClientToTime(int x)
|
|
{
|
|
return m_grid.ClientToWorld(QPoint(x, 0)).x;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::paintEvent(QPaintEvent* event)
|
|
{
|
|
QPainter painter(this);
|
|
|
|
QRect rcClient = rect();
|
|
|
|
{
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Fill keys background.
|
|
//////////////////////////////////////////////////////////////////////////
|
|
const QRect rc = rcClient.intersected(event->rect());
|
|
painter.fillRect(rc, palette().brush(QPalette::Button));
|
|
painter.drawRect(rc);
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
m_grid.CalculateGridLines();
|
|
|
|
DrawTicks(&painter);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
float TimelineWidget::SnapTime(float time)
|
|
{
|
|
double t = floor((double)time * m_ticksStep + 0.5);
|
|
t = t / m_ticksStep;
|
|
return t;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::DrawTicks(QPainter* painter)
|
|
{
|
|
const QRectF rc = rect();
|
|
|
|
const QPen pOldPen = painter->pen();
|
|
|
|
const QPen ltgray(QColor(110, 110, 110));
|
|
const QPen black(Qt::black);
|
|
const QPen redpen(QColor(255, 0, 255));
|
|
|
|
// Draw time ticks every tick step seconds.
|
|
Range timeRange = m_timeRange;
|
|
|
|
painter->setPen(ltgray);
|
|
|
|
switch (m_markerStyle)
|
|
{
|
|
case MARKER_STYLE_SECONDS:
|
|
DrawSecondTicks(painter);
|
|
break;
|
|
|
|
case MARKER_STYLE_FRAMES:
|
|
DrawFrameTicks(painter);
|
|
break;
|
|
}
|
|
|
|
painter->setPen(redpen);
|
|
int x = TimeToClient(m_fTimeMarker);
|
|
painter->setBrush(Qt::NoBrush);
|
|
painter->drawRect(QRect(QPoint(x - 3, rc.top()), QPoint(x + 4, rc.bottom())));
|
|
|
|
painter->setPen(redpen);
|
|
painter->drawLine(x, rc.top(), x, rc.bottom());
|
|
painter->setBrush(Qt::NoBrush);
|
|
|
|
// Draw vertical line showing current time.
|
|
{
|
|
int x2 = TimeToClient(m_fTimeMarker);
|
|
if (x2 > m_rcTimeline.left() && x2 < m_rcTimeline.right())
|
|
{
|
|
painter->setPen(QColor(255, 0, 255));
|
|
painter->drawLine(x2, 0, x2, m_rcTimeline.bottom());
|
|
}
|
|
}
|
|
|
|
// Draw the key times.
|
|
painter->setPen(redpen);
|
|
painter->setBrush(Qt::NoBrush);
|
|
const QPen keySelectedPen(QColor(100, 255, 255));
|
|
const QBrush keySelectedBrush(QColor(100, 255, 255));
|
|
for (int keyTimeIndex = 0; m_pKeyTimeSet && keyTimeIndex < m_pKeyTimeSet->GetKeyTimeCount(); ++keyTimeIndex)
|
|
{
|
|
int keyCountBound = __max(m_pKeyTimeSet->GetKeyCountBound(), 1);
|
|
int keyCount = __min(m_pKeyTimeSet->GetKeyCount(keyTimeIndex), keyCountBound);
|
|
float colorCodeFraction = float(keyCount) / keyCountBound;
|
|
const QColor keyMarkerCol = InterpolateColor(Qt::green, Qt::red, colorCodeFraction);
|
|
|
|
const QPen keyPen(keyMarkerCol);
|
|
const QBrush keyBrush(keyMarkerCol);
|
|
bool keyTimeSelected = m_pKeyTimeSet && m_pKeyTimeSet->GetKeyTimeSelected(keyTimeIndex);
|
|
painter->setBrush(keyTimeSelected ? keySelectedBrush : keyBrush);
|
|
painter->setPen(keyTimeSelected ? keySelectedPen : keyPen);
|
|
|
|
float keyTime = (m_pKeyTimeSet ? m_pKeyTimeSet->GetKeyTime(keyTimeIndex) : 0.0f);
|
|
|
|
int x2 = TimeToClient(keyTime);
|
|
painter->drawRect(QRect(QPoint(x2 - 2, rc.top()), QPoint(x2 + 3, rc.bottom())));
|
|
}
|
|
|
|
painter->setPen(pOldPen);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
Range TimelineWidget::GetVisibleRange() const
|
|
{
|
|
Range r;
|
|
|
|
r.start = (m_scrollOffset - m_leftOffset) / m_timeScale;
|
|
r.end = r.start + (m_rcTimeline.width()) / m_timeScale;
|
|
// Intersect range with global time range.
|
|
r = m_timeRange & r;
|
|
|
|
return r;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//Mouse Message Handlers
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::mousePressEvent(QMouseEvent* event)
|
|
{
|
|
switch (event->button())
|
|
{
|
|
case Qt::LeftButton:
|
|
OnLButtonDown(event->pos(), event->modifiers());
|
|
break;
|
|
case Qt::RightButton:
|
|
OnRButtonDown(event->pos(), event->modifiers());
|
|
break;
|
|
}
|
|
}
|
|
|
|
void TimelineWidget::mouseReleaseEvent(QMouseEvent* event)
|
|
{
|
|
switch (event->button())
|
|
{
|
|
case Qt::LeftButton:
|
|
OnLButtonUp(event->pos(), event->modifiers());
|
|
break;
|
|
case Qt::RightButton:
|
|
OnRButtonUp(event->pos(), event->modifiers());
|
|
break;
|
|
}
|
|
}
|
|
|
|
namespace
|
|
{
|
|
const float EDITOR_FPS = 30.0f;
|
|
float SnapTimeToFrame(float time) {return int((time * EDITOR_FPS) + 0.5f) * (1.0f / EDITOR_FPS); }
|
|
}
|
|
|
|
void TimelineWidget::OnLButtonDown(const QPoint& point, Qt::KeyboardModifiers modifiers)
|
|
{
|
|
if (m_trackingMode != TRACKING_MODE_NONE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Q_EMIT clicked();
|
|
|
|
int hitKeyTimeIndex = HitKeyTimes(point);
|
|
bool autoDeselect = !(modifiers& Qt::ControlModifier) && (m_pKeyTimeSet && ((hitKeyTimeIndex >= 0) ? !m_pKeyTimeSet->GetKeyTimeSelected(hitKeyTimeIndex) : true));
|
|
for (int keyTimeIndex = 0; m_pKeyTimeSet && keyTimeIndex < m_pKeyTimeSet->GetKeyTimeCount(); ++keyTimeIndex)
|
|
{
|
|
bool shouldBeSelected;
|
|
if (keyTimeIndex == hitKeyTimeIndex)
|
|
{
|
|
shouldBeSelected = (modifiers& Qt::ControlModifier) || !((modifiers& Qt::ShiftModifier) && m_pKeyTimeSet->GetKeyTimeSelected(keyTimeIndex));
|
|
}
|
|
else
|
|
{
|
|
shouldBeSelected = (!autoDeselect || (modifiers & Qt::ShiftModifier)) && m_pKeyTimeSet->GetKeyTimeSelected(keyTimeIndex);
|
|
}
|
|
|
|
m_pKeyTimeSet->SetKeyTimeSelected(keyTimeIndex, shouldBeSelected);
|
|
}
|
|
TrackingMode trackingMode = (hitKeyTimeIndex >= 0 ? TRACKING_MODE_MOVE_KEYS : TRACKING_MODE_NONE);
|
|
if (trackingMode == TRACKING_MODE_NONE)
|
|
{
|
|
trackingMode = ((modifiers& Qt::ControlModifier) ? TRACKING_MODE_SELECTION_RANGE : TRACKING_MODE_SET_TIME);
|
|
}
|
|
StartTracking(trackingMode);
|
|
|
|
switch (m_trackingMode)
|
|
{
|
|
case TRACKING_MODE_SET_TIME:
|
|
{
|
|
if (m_bTrackingSnapToFrames)
|
|
{
|
|
SetTimeMarker(SnapTimeToFrame(ClientToTime(point.x())));
|
|
}
|
|
else
|
|
{
|
|
SetTimeMarker(ClientToTime(point.x()));
|
|
}
|
|
CScopedVariableSetter<bool> ignoreSetTime(m_bIgnoreSetTime, true);
|
|
Q_EMIT startChange();
|
|
Q_EMIT change();
|
|
}
|
|
break;
|
|
|
|
case TRACKING_MODE_MOVE_KEYS:
|
|
m_bChangedKeyTimeSet = false;
|
|
m_copyKeyTimes = (modifiers & Qt::ControlModifier ? true : false);
|
|
break;
|
|
|
|
case TRACKING_MODE_NONE:
|
|
break;
|
|
}
|
|
|
|
m_lastPoint = point;
|
|
|
|
update();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::OnRButtonDown(const QPoint& point, [[maybe_unused]] Qt::KeyboardModifiers modifiers)
|
|
{
|
|
Q_EMIT clicked();
|
|
|
|
if (m_trackingMode != TRACKING_MODE_NONE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
StartTracking(TRACKING_MODE_SET_TIME);
|
|
|
|
if (m_bTrackingSnapToFrames)
|
|
{
|
|
SetTimeMarker(SnapTimeToFrame(ClientToTime(point.x())));
|
|
}
|
|
else
|
|
{
|
|
SetTimeMarker(ClientToTime(point.x()));
|
|
}
|
|
CScopedVariableSetter<bool> ignoreSetTime(m_bIgnoreSetTime, true);
|
|
Q_EMIT startChange();
|
|
Q_EMIT change();
|
|
|
|
update();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::OnRButtonUp([[maybe_unused]] const QPoint& point, [[maybe_unused]] Qt::KeyboardModifiers modifiers)
|
|
{
|
|
switch (m_trackingMode)
|
|
{
|
|
case TRACKING_MODE_SET_TIME:
|
|
{
|
|
Q_EMIT endChange();
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (m_trackingMode != TRACKING_MODE_NONE)
|
|
{
|
|
StopTracking();
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::keyPressEvent(QKeyEvent* event)
|
|
{
|
|
if (event->matches(QKeySequence::Delete))
|
|
{
|
|
Q_EMIT deleteRequested();
|
|
}
|
|
if (event->key() == Qt::Key_Space && m_playCallback)
|
|
{
|
|
m_playCallback();
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::mouseMoveEvent(QMouseEvent* event)
|
|
{
|
|
switch (m_trackingMode)
|
|
{
|
|
case TRACKING_MODE_SET_TIME:
|
|
{
|
|
if (m_bTrackingSnapToFrames)
|
|
{
|
|
SetTimeMarker(SnapTimeToFrame(ClientToTime(event->x())));
|
|
}
|
|
else
|
|
{
|
|
SetTimeMarker(ClientToTime(event->x()));
|
|
}
|
|
CScopedVariableSetter<bool> ignoreSetTime(m_bIgnoreSetTime, true);
|
|
Q_EMIT change();
|
|
}
|
|
break;
|
|
|
|
case TRACKING_MODE_MOVE_KEYS:
|
|
{
|
|
if (m_pKeyTimeSet && !m_bChangedKeyTimeSet)
|
|
{
|
|
m_bChangedKeyTimeSet = true;
|
|
m_pKeyTimeSet->BeginEdittingKeyTimes();
|
|
}
|
|
|
|
bool altClicked = Qt::AltModifier & QApplication::queryKeyboardModifiers();
|
|
float scale, offset;
|
|
float startTime = ClientToTime(m_lastPoint.x());
|
|
float endTime = ClientToTime(event->x());
|
|
if (altClicked)
|
|
{
|
|
// Alt was pressed, so we should scale the key times rather than translate.
|
|
// Calculate the scaling parameters (ie t1 = t0 * M + C).
|
|
scale = 1.0f;
|
|
if (fabsf(startTime - m_fTimeMarker) > 0.1)
|
|
{
|
|
scale = (endTime - m_fTimeMarker) / (startTime - m_fTimeMarker);
|
|
}
|
|
offset = endTime - startTime * scale;
|
|
}
|
|
else
|
|
{
|
|
// Simply move the keys.
|
|
offset = endTime - startTime;
|
|
scale = 1.0f;
|
|
}
|
|
|
|
MoveSelectedKeyTimes(scale, offset);
|
|
}
|
|
break;
|
|
|
|
case TRACKING_MODE_SELECTION_RANGE:
|
|
{
|
|
float start = min(ClientToTime(m_lastPoint.x()), ClientToTime(event->x()));
|
|
float end = max(ClientToTime(m_lastPoint.x()), ClientToTime(event->x()));
|
|
SelectKeysInRange(start, end, !(event->modifiers() & Qt::ShiftModifier));
|
|
m_lastPoint = event->pos();
|
|
update();
|
|
}
|
|
break;
|
|
|
|
case TRACKING_MODE_NONE:
|
|
break;
|
|
}
|
|
|
|
//m_lastPoint = point;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
QString TimelineWidget::TimeToString(float time)
|
|
{
|
|
return QString::number(time, 'f', 3);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::OnLButtonUp([[maybe_unused]] const QPoint& point, [[maybe_unused]] Qt::KeyboardModifiers modifiers)
|
|
{
|
|
switch (m_trackingMode)
|
|
{
|
|
case TRACKING_MODE_MOVE_KEYS:
|
|
{
|
|
if (m_pKeyTimeSet && m_bChangedKeyTimeSet)
|
|
{
|
|
m_pKeyTimeSet->EndEdittingKeyTimes();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TRACKING_MODE_SET_TIME:
|
|
{
|
|
Q_EMIT endChange();
|
|
}
|
|
break;
|
|
|
|
case TRACKING_MODE_NONE:
|
|
break;
|
|
}
|
|
|
|
if (m_trackingMode != TRACKING_MODE_NONE)
|
|
{
|
|
StopTracking();
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::StartTracking(TrackingMode trackingMode)
|
|
{
|
|
m_trackingMode = trackingMode;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::StopTracking()
|
|
{
|
|
if (!m_trackingMode)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_trackingMode = TRACKING_MODE_NONE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::SetTimeMarker(float fTime)
|
|
{
|
|
if (fTime < m_timeRange.start)
|
|
{
|
|
fTime = m_timeRange.start;
|
|
}
|
|
else if (fTime > m_timeRange.end)
|
|
{
|
|
fTime = m_timeRange.end;
|
|
}
|
|
|
|
if (fTime == m_fTimeMarker || m_bIgnoreSetTime)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int x0 = TimeToClient(m_fTimeMarker);
|
|
int x1 = TimeToClient(fTime);
|
|
QRect rc(QPoint(x0, m_rcClient.top()), QPoint(x1, m_rcClient.bottom()));
|
|
rc = rc.normalized();
|
|
rc.adjust(-5, 0, 5, 0);
|
|
update(rc);
|
|
|
|
m_fTimeMarker = fTime;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::SetZoom(float fZoom)
|
|
{
|
|
m_grid.zoom.x = fZoom;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::SetOrigin(float fOffset)
|
|
{
|
|
m_grid.origin.x = fOffset;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::SetKeyTimeSet(IKeyTimeSet* pKeyTimeSet)
|
|
{
|
|
m_pKeyTimeSet = pKeyTimeSet;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
int TimelineWidget::HitKeyTimes(const QPoint& point)
|
|
{
|
|
const int threshold = 3;
|
|
|
|
int hitKeyTimeIndex = -1;
|
|
for (int keyTimeIndex = 0; m_pKeyTimeSet && keyTimeIndex < m_pKeyTimeSet->GetKeyTimeCount(); ++keyTimeIndex)
|
|
{
|
|
float keyTime = (m_pKeyTimeSet ? m_pKeyTimeSet->GetKeyTime(keyTimeIndex) : 0.0f);
|
|
int x = TimeToClient(keyTime);
|
|
if (abs(point.x() - x) <= threshold)
|
|
{
|
|
hitKeyTimeIndex = keyTimeIndex;
|
|
}
|
|
}
|
|
|
|
return hitKeyTimeIndex;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::MoveSelectedKeyTimes(float scale, float offset)
|
|
{
|
|
std::vector<int> indices;
|
|
for (int keyTimeIndex = 0; m_pKeyTimeSet && keyTimeIndex < m_pKeyTimeSet->GetKeyTimeCount(); ++keyTimeIndex)
|
|
{
|
|
if (m_pKeyTimeSet && m_pKeyTimeSet->GetKeyTimeSelected(keyTimeIndex))
|
|
{
|
|
indices.push_back(keyTimeIndex);
|
|
}
|
|
}
|
|
|
|
if (m_pKeyTimeSet)
|
|
{
|
|
m_pKeyTimeSet->MoveKeyTimes(int(indices.size()), &indices[0], scale, offset, m_copyKeyTimes);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::SelectKeysInRange(float start, float end, bool select)
|
|
{
|
|
for (int keyTimeIndex = 0; m_pKeyTimeSet && keyTimeIndex < m_pKeyTimeSet->GetKeyTimeCount(); ++keyTimeIndex)
|
|
{
|
|
float time = (m_pKeyTimeSet ? m_pKeyTimeSet->GetKeyTime(keyTimeIndex) : 0.0f);
|
|
if (m_pKeyTimeSet && time >= start && time <= end)
|
|
{
|
|
m_pKeyTimeSet->SetKeyTimeSelected(keyTimeIndex, select);
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::SetMarkerStyle(MarkerStyle markerStyle)
|
|
{
|
|
m_markerStyle = markerStyle;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::SetFPS(float fps)
|
|
{
|
|
m_fps = fps;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void TimelineWidget::DrawSecondTicks(QPainter* painter)
|
|
{
|
|
const QPen ltgray(QColor(110, 110, 110));
|
|
const QPen black(Qt::black);
|
|
const QPen redpen(QColor(255, 0, 255));
|
|
|
|
for (int gx = m_grid.firstGridLine.x(); gx < m_grid.firstGridLine.x() + m_grid.numGridLines.x() + 1; gx++)
|
|
{
|
|
painter->setPen(ltgray);
|
|
|
|
int x = m_grid.GetGridLineX(gx);
|
|
if (x < 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
painter->drawLine(m_rcTimeline.left() + x, m_rcTimeline.bottom() - 2, m_rcTimeline.left() + x, m_rcTimeline.bottom() - 4);
|
|
|
|
//if (gx % 10 == 0)
|
|
{
|
|
float t = m_grid.GetGridLineXValue(gx);
|
|
t = floor(t * 1000.0f + 0.5f) / 1000.0f;
|
|
|
|
const QString str = QString::number(t * m_fTicksTextScale, 'g');
|
|
|
|
//t = t / pow(10,precision);
|
|
painter->setPen(black);
|
|
painter->drawLine(m_rcTimeline.left() + x, m_rcTimeline.bottom() - 2, m_rcTimeline.left() + x, m_rcTimeline.bottom() - 14);
|
|
painter->drawText(m_rcTimeline.left() + x + 2, m_rcTimeline.top(), str);
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
class TickDrawer
|
|
{
|
|
public:
|
|
TickDrawer(QPainter* painter, const QRect& rect)
|
|
: rect(rect)
|
|
, painter(painter)
|
|
{
|
|
}
|
|
|
|
void operator()(int frameIndex, int x)
|
|
{
|
|
if (painter)
|
|
{
|
|
painter->setPen(QColor(110, 110, 110));
|
|
painter->drawLine(rect.left() + x, rect.bottom() - 2, rect.left() + x, rect.bottom() - 4);
|
|
|
|
{
|
|
const QString str = QString::number(frameIndex);
|
|
|
|
painter->setPen(Qt::black);
|
|
painter->drawLine(rect.left() + x, rect.bottom() - 2, rect.left() + x, rect.bottom() - 14);
|
|
painter->drawText(rect.left() + x + 2, rect.top(), str);
|
|
}
|
|
}
|
|
}
|
|
|
|
QRect rect;
|
|
QPainter* painter;
|
|
};
|
|
|
|
void TimelineWidget::DrawFrameTicks(QPainter* painter)
|
|
{
|
|
TickDrawer tickDrawer(painter, m_rcTimeline);
|
|
GridUtils::IterateGrid(tickDrawer, 50.0f, m_grid.zoom.x, m_grid.origin.x, m_fps, m_grid.rect.left(), m_grid.rect.right() + 1);
|
|
}
|
|
|
|
void TimelineWidget::SetPlayCallback(const std::function<void()>& callback)
|
|
{
|
|
m_playCallback = callback;
|
|
}
|
|
|
|
|
|
#include <Animation/Controls/moc_UiTimelineCtrl.cpp>
|