新增根据帧数控制可见性

This commit is contained in:
2026-04-09 17:30:55 +08:00
parent e116a9ec79
commit d67d7dc0c5
29 changed files with 4387 additions and 408 deletions

View File

@@ -1,33 +1,41 @@
#pragma once
#include "core/domain/Project.h"
#include <QWidget>
class QResizeEvent;
class TimelineWidget final : public QWidget {
Q_OBJECT
public:
explicit TimelineWidget(QWidget* parent = nullptr);
// 兼容旧接口NLA/片段系统下时间轴始终固定为 0..600local frame
void setFrameRange(int start, int end);
void setCurrentFrame(int frame);
/// 由主窗口同步工程帧时调用:不发射 frameScrubbed避免与拖动/刷新打架造成数字闪烁
void setCurrentFrameProgrammatic(int frame);
int currentFrame() const { return m_currentFrame; }
void setSelectionRange(int start, int end); // -1,-1 清除
int selectionStart() const { return m_selStart; }
int selectionEnd() const { return m_selEnd; }
// 只显示“当前选中实体”的关键帧标记
void setKeyframeTracks(const core::Project::Entity* entityOrNull);
// 轨道数据直接由上层提供(通常来自当前条带引用的 clip
void setKeyframeTracks(const QVector<int>& locFrames,
const QVector<int>& scaleFrames,
const QVector<int>& imgFrames,
const QVector<int>& visFrames);
void setToolKeyframeTracks(const QVector<int>& locFrames,
const QVector<int>& visFrames);
enum class KeyKind { None, Location, UserScale, Image };
enum class KeyKind { None, Location, UserScale, Image, Visibility };
KeyKind selectedKeyKind() const { return m_selKeyKind; }
int selectedKeyFrame() const { return m_selKeyFrame; }
bool hasSelectedKeyframe() const { return m_selKeyKind != KeyKind::None && m_selKeyFrame >= 0; }
signals:
void frameScrubbed(int frame); // 拖动中实时触发(用于实时预览)
void frameCommitted(int frame); // 松手/点击确认(用于较重的刷新)
void frameScrubbed(int frame);
void frameCommitted(int frame);
void contextMenuRequested(const QPoint& globalPos, int frame);
void keyframeSelectionChanged(KeyKind kind, int frame);
void intervalSelectionChanged(int start, int end);
@@ -38,18 +46,26 @@ protected:
void mouseMoveEvent(QMouseEvent*) override;
void mouseReleaseEvent(QMouseEvent*) override;
void wheelEvent(QWheelEvent*) override;
void resizeEvent(QResizeEvent* e) override;
private:
int xToFrame(int x) const;
int contentLeft() const { return 6; }
int contentWidth() const { return std::max(1, width() - 12); }
QRect contentRect() const;
double frameToXf(double frame) const;
int frameToX(int frame) const;
QRect trackRect() const;
double xToFramef(int x) const;
int xToFrame(int x) const;
QRect rulerRect() const;
QRect keyAreaRect() const;
void setFrameInternal(int frame, bool commit);
private:
int m_start = 0;
int m_end = 600;
int m_currentFrame = 0;
static constexpr int kStart = 0;
static constexpr int kEnd = 600; // exclusive for mapping, inclusive for UI labels
int m_currentFrame = 0; // local frame: 0..599
int m_selStart = -1;
int m_selEnd = -1;
@@ -58,12 +74,13 @@ private:
QPoint m_pressPos;
bool m_moved = false;
// snapshot避免频繁遍历 workspace
static constexpr int kRulerHeight = 14;
QVector<int> m_locFrames;
QVector<int> m_scaleFrames;
QVector<int> m_imgFrames;
QVector<int> m_visFrames;
KeyKind m_selKeyKind = KeyKind::None;
int m_selKeyFrame = -1;
};