update
This commit is contained in:
@@ -687,8 +687,11 @@ void EditorCanvas::setEntities(const QVector<core::Project::Entity>& entities,
|
||||
const QString prevSelectedId =
|
||||
(m_selectedEntity >= 0 && m_selectedEntity < m_entities.size()) ? m_entities[m_selectedEntity].id : QString();
|
||||
|
||||
m_blackholeOverlayImageCache.clear();
|
||||
m_projectDirAbs = projectDirAbs;
|
||||
if (m_entityRasterCacheProjectDir != projectDirAbs) {
|
||||
m_entityRasterImageCache.clear();
|
||||
m_entityRasterCacheProjectDir = projectDirAbs;
|
||||
}
|
||||
|
||||
m_entities.clear();
|
||||
m_entities.reserve(entities.size());
|
||||
@@ -761,37 +764,87 @@ void EditorCanvas::setEntities(const QVector<core::Project::Entity>& entities,
|
||||
v.color = QColor(255, 120, 0, 70);
|
||||
|
||||
if (!e.runtimeImagePng.isEmpty()) {
|
||||
QImage img;
|
||||
img.loadFromData(e.runtimeImagePng, "PNG");
|
||||
if (!img.isNull() && img.format() != QImage::Format_ARGB32_Premultiplied) {
|
||||
img = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
const QString cacheKey = QStringLiteral("rt:%1:%2:%3")
|
||||
.arg(e.id)
|
||||
.arg(e.runtimeImagePng.size())
|
||||
.arg(qHash(e.runtimeImagePng));
|
||||
auto cit = m_entityRasterImageCache.constFind(cacheKey);
|
||||
if (cit != m_entityRasterImageCache.cend() && !cit->isNull()) {
|
||||
v.image = cit.value();
|
||||
} else {
|
||||
QImage img;
|
||||
img.loadFromData(e.runtimeImagePng, "PNG");
|
||||
if (!img.isNull() && img.format() != QImage::Format_ARGB32_Premultiplied) {
|
||||
img = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
}
|
||||
if (!img.isNull()) {
|
||||
m_entityRasterImageCache.insert(cacheKey, img);
|
||||
}
|
||||
v.image = img;
|
||||
}
|
||||
v.image = img;
|
||||
} else {
|
||||
const QString imgRel = e.imagePath;
|
||||
if (imgRel.startsWith(QStringLiteral("pngb64:"))) {
|
||||
const QByteArray b64 = imgRel.mid(QStringLiteral("pngb64:").size()).toLatin1();
|
||||
const QByteArray raw = QByteArray::fromBase64(b64);
|
||||
QImage img;
|
||||
img.loadFromData(raw, "PNG");
|
||||
if (!img.isNull() && img.format() != QImage::Format_ARGB32_Premultiplied) {
|
||||
img = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
}
|
||||
v.image = img;
|
||||
} else if (!imgRel.isEmpty() && !projectDirAbs.isEmpty()) {
|
||||
const QString abs = QDir(projectDirAbs).filePath(imgRel);
|
||||
if (QFileInfo::exists(abs)) {
|
||||
QImage img(abs);
|
||||
const QString cacheKey =
|
||||
QStringLiteral("b64:%1:%2").arg(raw.size()).arg(qHash(raw));
|
||||
auto cit = m_entityRasterImageCache.constFind(cacheKey);
|
||||
if (cit != m_entityRasterImageCache.cend() && !cit->isNull()) {
|
||||
v.image = cit.value();
|
||||
} else {
|
||||
QImage img;
|
||||
img.loadFromData(raw, "PNG");
|
||||
if (!img.isNull() && img.format() != QImage::Format_ARGB32_Premultiplied) {
|
||||
img = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
}
|
||||
if (!img.isNull()) {
|
||||
m_entityRasterImageCache.insert(cacheKey, img);
|
||||
}
|
||||
v.image = img;
|
||||
}
|
||||
} else if (!imgRel.isEmpty() && !projectDirAbs.isEmpty()) {
|
||||
const QString abs = QDir::cleanPath(QDir(projectDirAbs).filePath(imgRel));
|
||||
if (QFileInfo::exists(abs)) {
|
||||
auto cit = m_entityRasterImageCache.constFind(abs);
|
||||
if (cit != m_entityRasterImageCache.cend() && !cit->isNull()) {
|
||||
v.image = cit.value();
|
||||
} else {
|
||||
QImage img(abs);
|
||||
if (!img.isNull() && img.format() != QImage::Format_ARGB32_Premultiplied) {
|
||||
img = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
}
|
||||
if (!img.isNull()) {
|
||||
m_entityRasterImageCache.insert(abs, img);
|
||||
}
|
||||
v.image = img;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_entities.push_back(v);
|
||||
}
|
||||
|
||||
constexpr int kMaxEntityRasterCacheEntries = 768;
|
||||
if (m_entityRasterImageCache.size() > kMaxEntityRasterCacheEntries) {
|
||||
m_entityRasterImageCache.clear();
|
||||
}
|
||||
|
||||
if (!m_blackholeOverlayImageCache.isEmpty()) {
|
||||
QSet<QString> aliveIds;
|
||||
aliveIds.reserve(m_entities.size());
|
||||
for (const auto& ent : m_entities) {
|
||||
aliveIds.insert(ent.id);
|
||||
}
|
||||
for (auto it = m_blackholeOverlayImageCache.begin(); it != m_blackholeOverlayImageCache.end();) {
|
||||
if (!aliveIds.contains(it.key())) {
|
||||
it = m_blackholeOverlayImageCache.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 绘制/命中顺序:
|
||||
// - priority 小(低)先画,大(高)后画,高优先级盖住低优先级
|
||||
// - priority 相同:深度小(远)先画,大(近)后画,近处盖住远处(等价于按距离缩放决定上下层)
|
||||
@@ -816,13 +869,15 @@ void EditorCanvas::setEntities(const QVector<core::Project::Entity>& entities,
|
||||
}
|
||||
}
|
||||
|
||||
if (m_selectedEntity >= 0) {
|
||||
const auto& ent = m_entities[m_selectedEntity];
|
||||
const QPointF origin =
|
||||
ent.polygonWorld.isEmpty() ? ent.rect.center() : entity_cutout::polygonCentroid(ent.polygonWorld);
|
||||
emit selectedEntityChanged(true, ent.id, ent.depth, origin);
|
||||
} else if (!prevSelectedId.isEmpty()) {
|
||||
emit selectedEntityChanged(false, QString(), 0, QPointF());
|
||||
if (!m_suppressSelectionSignals) {
|
||||
if (m_selectedEntity >= 0) {
|
||||
const auto& ent = m_entities[m_selectedEntity];
|
||||
const QPointF origin =
|
||||
ent.polygonWorld.isEmpty() ? ent.rect.center() : entity_cutout::polygonCentroid(ent.polygonWorld);
|
||||
emit selectedEntityChanged(true, ent.id, ent.depth, origin);
|
||||
} else if (!prevSelectedId.isEmpty()) {
|
||||
emit selectedEntityChanged(false, QString(), 0, QPointF());
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_selectedBlackholeEntityId.isEmpty()) {
|
||||
@@ -3375,6 +3430,8 @@ void EditorCanvas::mouseReleaseEvent(QMouseEvent* e) {
|
||||
e->button() == Qt::LeftButton) {
|
||||
const auto& cam = m_cameraOverlays[m_selectedCameraIndex];
|
||||
const QPointF delta = cam.centerWorld - m_cameraDragStartCenterWorld;
|
||||
// 先于 requestMoveCamera 清除:MainWindow::refreshEditorPage 需刷新 overlays,否则会误判“仍在拖动”而跳过 setCameraOverlays
|
||||
m_draggingCamera = false;
|
||||
if (!cam.id.isEmpty() && (!qFuzzyIsNull(delta.x()) || !qFuzzyIsNull(delta.y()))) {
|
||||
emit requestMoveCamera(cam.id, delta);
|
||||
} else if (!cam.id.isEmpty()) {
|
||||
|
||||
@@ -95,6 +95,8 @@ public:
|
||||
void setEntities(const QVector<core::Project::Entity>& entities,
|
||||
const QVector<double>& opacities01,
|
||||
const QString& projectDirAbs);
|
||||
/// 播放/时间轴轻量刷帧时置 true,避免 setEntities 每帧 emit selectedEntityChanged 拖垮主线程
|
||||
void setSuppressSelectionSignals(bool on) { m_suppressSelectionSignals = on; }
|
||||
void setTools(const QVector<core::Project::Tool>& tools, const QVector<double>& opacities01);
|
||||
void setCameraOverlays(const QVector<core::Project::Camera>& cameras,
|
||||
const QString& selectedId,
|
||||
@@ -107,6 +109,8 @@ public:
|
||||
int currentFrame() const { return m_currentFrame; }
|
||||
|
||||
bool isDraggingEntity() const { return m_draggingEntity; }
|
||||
/// 正在拖动摄像机中心手柄(Move 工具);此时 overlays 由画布更新,勿用工作区求值覆盖
|
||||
bool isDraggingCamera() const { return m_draggingCamera; }
|
||||
|
||||
void selectEntityById(const QString& id);
|
||||
void clearEntitySelection();
|
||||
@@ -252,6 +256,10 @@ private:
|
||||
|
||||
private:
|
||||
QString m_projectDirAbs;
|
||||
/// 实体抠图贴图缓存(键:磁盘绝对路径或 runtime/png 内容摘要),避免播放时每帧 QImage(path) 读盘
|
||||
QHash<QString, QImage> m_entityRasterImageCache;
|
||||
QString m_entityRasterCacheProjectDir;
|
||||
bool m_suppressSelectionSignals = false;
|
||||
QHash<QString, QImage> m_blackholeOverlayImageCache;
|
||||
QString m_bgAbsPath;
|
||||
bool m_backgroundVisible = true;
|
||||
|
||||
Reference in New Issue
Block a user