initial commit

This commit is contained in:
2026-04-07 20:55:30 +08:00
commit 81d1fb7856
84 changed files with 11929 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,179 @@
#pragma once
#include "core/domain/Project.h"
#include <QPixmap>
#include <QPointF>
#include <QImage>
#include <QPainterPath>
#include <QVector>
#include <QWidget>
#include <QElapsedTimer>
class EditorCanvas final : public QWidget {
Q_OBJECT
public:
enum class Tool { Move, Zoom, CreateEntity };
Q_ENUM(Tool)
explicit EditorCanvas(QWidget* parent = nullptr);
void setBackgroundImagePath(const QString& absolutePath);
QString backgroundImagePath() const { return m_bgAbsPath; }
void setBackgroundVisible(bool on);
bool backgroundVisible() const { return m_backgroundVisible; }
void setDepthMapPath(const QString& absolutePath);
void setDepthOverlayEnabled(bool on);
bool depthOverlayEnabled() const { return m_depthOverlayEnabled; }
void setTool(Tool tool);
Tool tool() const { return m_tool; }
void resetView();
void zoomToFit();
void setWorldAxesVisible(bool on);
bool worldAxesVisible() const { return m_worldAxesVisible; }
void setAxisLabelsVisible(bool on);
bool axisLabelsVisible() const { return m_axisLabelsVisible; }
void setGizmoLabelsVisible(bool on);
bool gizmoLabelsVisible() const { return m_gizmoLabelsVisible; }
void setGridVisible(bool on);
bool gridVisible() const { return m_gridVisible; }
void setCheckerboardVisible(bool on);
bool checkerboardVisible() const { return m_checkerboardVisible; }
// 预览呈现:完整背景 + 全部实体(忽略显隐开关),隐藏编辑辅助元素,仅可平移/缩放查看
void setPresentationPreviewMode(bool on);
bool presentationPreviewMode() const { return m_presentationPreviewMode; }
void setEntities(const QVector<core::Project::Entity>& entities, const QString& projectDirAbs);
void setCurrentFrame(int frame);
int currentFrame() const { return m_currentFrame; }
bool isDraggingEntity() const { return m_draggingEntity; }
void selectEntityById(const QString& id);
void clearEntitySelection();
// 与动画求值一致的原点/缩放(用于 K 帧与自动关键帧)
QPointF selectedAnimatedOriginWorld() const;
double selectedDepthScale01() const;
QPointF selectedEntityCentroidWorld() const;
double selectedDistanceScaleMultiplier() const;
double selectedUserScale() const;
double selectedCombinedScale() const;
enum class DragMode { None, Free, AxisX, AxisY };
signals:
void hoveredWorldPosChanged(const QPointF& worldPos);
void hoveredWorldPosDepthChanged(const QPointF& worldPos, int depthZ);
void selectedEntityChanged(bool hasSelection, const QString& id, int depth, const QPointF& originWorld);
void requestAddEntity(const core::Project::Entity& entity, const QImage& image);
void requestMoveEntity(const QString& id, const QPointF& delta);
void entityDragActiveChanged(bool on);
void selectedEntityPreviewChanged(const QString& id, int depth, const QPointF& originWorld);
protected:
void paintEvent(QPaintEvent* e) override;
void resizeEvent(QResizeEvent* e) override;
void mousePressEvent(QMouseEvent* e) override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void wheelEvent(QWheelEvent* e) override;
private:
void ensurePixmapLoaded() const;
void invalidatePixmap();
void updateCursor();
QPointF viewToWorld(const QPointF& v) const;
QPointF worldToView(const QPointF& w) const;
QRectF worldRectOfBackground() const;
private:
struct Entity {
QString id;
QRectF rect; // world 坐标(用于拖拽与约束)
QVector<QPointF> polygonWorld; // 非空则使用 polygon
QPainterPath pathWorld; // polygonWorld 对应的 world 路径(缓存,避免每帧重建)
QVector<QPointF> cutoutPolygonWorld;
QColor color;
// 实体独立信息:
int depth = 0; // 0..255,来自划分区域平均深度
QImage image; // 抠图后的实体图像(带透明)
QPointF imageTopLeft; // image 对应的 world 左上角
double visualScale = 1.0; // 实体在 world 坐标下的缩放(用于贴图绘制)
double userScale = 1.0; // 与深度距离缩放相乘
QPointF animatedOriginWorld;
double animatedDepthScale01 = 0.5;
// 编辑模式下实体被设为隐藏时:不响应点选且不绘制,除非当前选中(便于树选隐藏实体)
bool hiddenInEditMode = false;
};
int hitTestEntity(const QPointF& worldPos) const;
private:
QString m_bgAbsPath;
bool m_backgroundVisible = true;
mutable QPixmap m_bgPixmap;
mutable bool m_pixmapDirty = true;
mutable QImage m_bgImage; // 原背景(用于抠图/填充)
mutable QImage m_bgImageCutout; // 抠图后的背景(实体区域填黑)
mutable bool m_bgImageDirty = true;
mutable bool m_bgCutoutDirty = true;
QString m_depthAbsPath;
mutable QImage m_depthImage8;
mutable bool m_depthDirty = true;
bool m_depthOverlayEnabled = false;
int m_depthOverlayAlpha = 110;
bool m_worldAxesVisible = true;
bool m_axisLabelsVisible = true;
bool m_gizmoLabelsVisible = true;
bool m_gridVisible = true;
bool m_checkerboardVisible = true;
bool m_presentationPreviewMode = false;
Tool m_tool = Tool::Move;
qreal m_scale = 1.0;
QPointF m_pan; // world 原点对应的 view 坐标偏移view = world*scale + pan
bool m_dragging = false;
bool m_draggingEntity = false;
bool m_drawingEntity = false;
QPointF m_lastMouseView;
// 拖动以“实体原点 animatedOriginWorld”为基准避免因缩放导致 rect/topLeft 抖动
QPointF m_entityDragOffsetOriginWorld;
QPointF m_entityDragStartAnimatedOrigin;
// 拖动性能优化:拖动过程中不逐点修改 polygonWorld而是保留基准形状+增量参数,在 paint 时做变换预览
bool m_dragPreviewActive = false;
QVector<QPointF> m_dragPolyBase;
QPainterPath m_dragPathBase;
QPointF m_dragImageTopLeftBase;
QRectF m_dragRectBase;
QPointF m_dragOriginBase;
QPointF m_dragDelta; // 纯平移
QPointF m_dragCentroidBase;
double m_dragScaleBase = 1.0; // 拖动开始时的 visualScale
double m_dragScaleRatio = 1.0; // 相对 m_dragScaleBase 的缩放比(由深度重算驱动)
QElapsedTimer m_previewEmitTimer;
qint64 m_lastPreviewEmitMs = 0;
qint64 m_lastDepthScaleRecalcMs = 0;
int m_selectedEntity = -1;
DragMode m_dragMode = DragMode::None;
QPointF m_dragStartMouseWorld;
QVector<Entity> m_entities;
QVector<QPointF> m_strokeWorld;
int m_currentFrame = 0;
};