update
This commit is contained in:
@@ -2,9 +2,11 @@
|
||||
|
||||
#include "domain/EntityIntro.h"
|
||||
|
||||
#include <QRect>
|
||||
#include <QString>
|
||||
#include <QPointF>
|
||||
#include <QHash>
|
||||
#include <QByteArray>
|
||||
#include <QVector>
|
||||
|
||||
#include <algorithm>
|
||||
@@ -59,9 +61,16 @@ public:
|
||||
bool blackholeVisible = true;
|
||||
// 背景空缺修复方案:copy_background / use_original_background / model_inpaint(预留)
|
||||
QString blackholeResolvedBy;
|
||||
/// 修复结果相对项目根路径;与 blackholeOverlayRect 一起用于画布叠加,不修改 background 原图
|
||||
QString blackholeOverlayPath;
|
||||
/// 覆盖层在背景图坐标系中的像素矩形;宽或高 <=0 表示无
|
||||
QRect blackholeOverlayRect;
|
||||
QPointF originWorld;
|
||||
int depth = 0; // 0..255
|
||||
int priority = 1; // 0=背景之上最底层;越大越靠上(同优先级再按距离缩放/深度)
|
||||
QString imagePath; // 相对路径,例如 "assets/entities/entity-1.png"
|
||||
QByteArray defaultImagePng; // 默认贴图 PNG bytes(不兼容旧路径工程时此为唯一来源)
|
||||
QByteArray runtimeImagePng; // 运行时求值后的 PNG bytes(不序列化)
|
||||
QPointF imageTopLeftWorld; // 贴图左上角 world 坐标
|
||||
// 人为整体缩放,与深度驱动的距离缩放相乘(画布中 visualScale = distanceScale * userScale;
|
||||
// distanceScale 在有 distanceScaleCalibMult 时为 (0.5+depth01)/calib,使抠图处为 1.0)
|
||||
@@ -73,8 +82,7 @@ public:
|
||||
// 约定:对话气泡等 UI 元素默认打开。
|
||||
bool ignoreDistanceScale = false;
|
||||
|
||||
// 父子关系:当 parentId 非空时,实体会保持相对父实体的偏移(world 坐标)。
|
||||
// parentOffsetWorld 表示「childOrigin - parentOrigin」在 world 中的偏移。
|
||||
// 父子关系:在「原点已与形心对齐」时,parentOffsetWorld 表示子形心相对父形心的世界偏移;否则为子原点相对父原点的偏移(与求值器一致)。
|
||||
QString parentId;
|
||||
QPointF parentOffsetWorld;
|
||||
|
||||
@@ -97,9 +105,6 @@ public:
|
||||
|
||||
// v2:project.json 仅存 id + payload,几何与动画在 entityPayloadPath(.hfe)中。
|
||||
QString entityPayloadPath; // 例如 "assets/entities/entity-1.hfe"
|
||||
// 仅打开 v1 项目时由 JSON 的 animationBundle 填入,用于合并旧 .anim;保存 v2 前应为空。
|
||||
QString legacyAnimSidecarPath;
|
||||
|
||||
QVector<KeyframeVec2> locationKeys;
|
||||
QVector<KeyframeFloat01> depthScaleKeys;
|
||||
QVector<KeyframeDouble> userScaleKeys;
|
||||
@@ -128,6 +133,7 @@ public:
|
||||
|
||||
// 基准位置(无关键帧时使用)
|
||||
QPointF originWorld;
|
||||
int priority = 10; // 默认高于实体(实体默认 1);越大越靠上
|
||||
QVector<Entity::KeyframeVec2> locationKeys;
|
||||
|
||||
// 可见性轨道:布尔关键帧(显示/隐藏);渲染时会被解释为“10 帧淡入淡出”。
|
||||
@@ -166,96 +172,79 @@ public:
|
||||
void setActiveCameraId(const QString& id) { m_activeCameraId = id; }
|
||||
const QString& activeCameraId() const { return m_activeCameraId; }
|
||||
|
||||
// —— 动画系统(Blender/NLA 风格简化版,工程级)——
|
||||
struct AnimationClip {
|
||||
// —— 动画系统(Godot AnimationPlayer 风格简化版)——
|
||||
enum class AnimationTargetKind { Entity, Tool, Camera };
|
||||
enum class AnimationProperty { Position, UserScale, Sprite, Visibility, DepthScale, CameraScale, Priority };
|
||||
enum class AnimationValueType { Vec2, Double, Bool, ImagePath, PngBytes };
|
||||
enum class AnimationInterpolation { Hold, Linear };
|
||||
|
||||
struct AnimationKey {
|
||||
int frame = 0;
|
||||
QPointF vec2Value;
|
||||
double numberValue = 0.0;
|
||||
bool boolValue = true;
|
||||
QString stringValue;
|
||||
QByteArray bytesValue;
|
||||
};
|
||||
|
||||
struct AnimationTrack {
|
||||
QString id;
|
||||
AnimationTargetKind targetKind = AnimationTargetKind::Entity;
|
||||
QString targetId;
|
||||
AnimationProperty property = AnimationProperty::Position;
|
||||
AnimationValueType valueType = AnimationValueType::Vec2;
|
||||
AnimationInterpolation interpolation = AnimationInterpolation::Linear;
|
||||
QVector<AnimationKey> keys;
|
||||
};
|
||||
|
||||
struct Animation {
|
||||
QString id;
|
||||
QString name;
|
||||
|
||||
// Entity channels (keyed by entity id)
|
||||
QHash<QString, QVector<Entity::KeyframeVec2>> entityLocationKeys;
|
||||
QHash<QString, QVector<Entity::KeyframeDouble>> entityUserScaleKeys;
|
||||
QHash<QString, QVector<Entity::ImageFrame>> entityImageFrames;
|
||||
QHash<QString, QVector<ToolKeyframeBool>> entityVisibilityKeys;
|
||||
|
||||
// Tool channels (keyed by tool id)
|
||||
QHash<QString, QVector<Entity::KeyframeVec2>> toolLocationKeys;
|
||||
QHash<QString, QVector<ToolKeyframeBool>> toolVisibilityKeys;
|
||||
|
||||
QHash<QString, QVector<Entity::KeyframeVec2>> cameraLocationKeys;
|
||||
QHash<QString, QVector<Entity::KeyframeDouble>> cameraScaleKeys;
|
||||
QString payloadPath; // 例如 "assets/animations/animation-1.hfa"
|
||||
int fps = 30;
|
||||
int lengthFrames = kClipFixedFrames;
|
||||
bool loop = true;
|
||||
QVector<AnimationTrack> tracks;
|
||||
};
|
||||
|
||||
struct NlaStrip {
|
||||
void setAnimations(const QVector<Animation>& animations) { m_animations = animations; }
|
||||
const QVector<Animation>& animations() const { return m_animations; }
|
||||
|
||||
void setActiveAnimationId(const QString& id) { m_activeAnimationId = id; }
|
||||
const QString& activeAnimationId() const { return m_activeAnimationId; }
|
||||
|
||||
const Animation* findAnimationById(const QString& id) const {
|
||||
for (const auto& a : m_animations) {
|
||||
if (a.id == id) return &a;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
Animation* findAnimationById(const QString& id) {
|
||||
for (auto& a : m_animations) {
|
||||
if (a.id == id) return &a;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
const Animation* activeAnimationOrNull() const {
|
||||
const Animation* a = findAnimationById(m_activeAnimationId);
|
||||
if (a) return a;
|
||||
return m_animations.isEmpty() ? nullptr : &m_animations.front();
|
||||
}
|
||||
Animation* activeAnimationOrNull() {
|
||||
Animation* a = findAnimationById(m_activeAnimationId);
|
||||
if (a) return a;
|
||||
return m_animations.isEmpty() ? nullptr : &m_animations.front();
|
||||
}
|
||||
|
||||
struct PresentationHotspot {
|
||||
QString id;
|
||||
QString clipId;
|
||||
int startSlot = 0; // slot index; 1 slot = kClipFixedFrames frames
|
||||
int slotLen = 1; // currently fixed to 1; reserved for future
|
||||
bool enabled = true;
|
||||
bool muted = false;
|
||||
QPointF centerWorld;
|
||||
QString targetAnimationId;
|
||||
};
|
||||
|
||||
struct NlaTrack {
|
||||
QString id;
|
||||
QString name;
|
||||
bool muted = false;
|
||||
bool solo = false;
|
||||
QVector<NlaStrip> strips;
|
||||
};
|
||||
|
||||
struct AnimationScheme {
|
||||
QString id;
|
||||
QString name;
|
||||
QVector<NlaTrack> tracks;
|
||||
};
|
||||
|
||||
void setAnimationClips(const QVector<AnimationClip>& clips) { m_clips = clips; }
|
||||
const QVector<AnimationClip>& animationClips() const { return m_clips; }
|
||||
|
||||
void setAnimationSchemes(const QVector<AnimationScheme>& schemes) { m_schemes = schemes; }
|
||||
const QVector<AnimationScheme>& animationSchemes() const { return m_schemes; }
|
||||
|
||||
void setActiveSchemeId(const QString& id) { m_activeSchemeId = id; }
|
||||
const QString& activeSchemeId() const { return m_activeSchemeId; }
|
||||
|
||||
void setSelectedStripId(const QString& id) { m_selectedStripId = id; }
|
||||
const QString& selectedStripId() const { return m_selectedStripId; }
|
||||
|
||||
const AnimationScheme* findSchemeById(const QString& id) const {
|
||||
for (const auto& s : m_schemes) {
|
||||
if (s.id == id) return &s;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
AnimationScheme* findSchemeById(const QString& id) {
|
||||
for (auto& s : m_schemes) {
|
||||
if (s.id == id) return &s;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const AnimationClip* findClipById(const QString& id) const {
|
||||
for (const auto& c : m_clips) {
|
||||
if (c.id == id) return &c;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
AnimationClip* findClipById(const QString& id) {
|
||||
for (auto& c : m_clips) {
|
||||
if (c.id == id) return &c;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const AnimationScheme* activeSchemeOrNull() const {
|
||||
const AnimationScheme* s = findSchemeById(m_activeSchemeId);
|
||||
if (s) return s;
|
||||
return m_schemes.isEmpty() ? nullptr : &m_schemes.front();
|
||||
}
|
||||
AnimationScheme* activeSchemeOrNull() {
|
||||
AnimationScheme* s = findSchemeById(m_activeSchemeId);
|
||||
if (s) return s;
|
||||
return m_schemes.isEmpty() ? nullptr : &m_schemes.front();
|
||||
}
|
||||
void setPresentationHotspots(const QVector<PresentationHotspot>& v) { m_presentationHotspots = v; }
|
||||
const QVector<PresentationHotspot>& presentationHotspots() const { return m_presentationHotspots; }
|
||||
QVector<PresentationHotspot>& presentationHotspotsRef() { return m_presentationHotspots; }
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
@@ -271,10 +260,9 @@ private:
|
||||
QVector<Camera> m_cameras;
|
||||
QString m_activeCameraId;
|
||||
|
||||
QVector<AnimationClip> m_clips;
|
||||
QVector<AnimationScheme> m_schemes;
|
||||
QString m_activeSchemeId;
|
||||
QString m_selectedStripId;
|
||||
QVector<Animation> m_animations;
|
||||
QString m_activeAnimationId;
|
||||
QVector<PresentationHotspot> m_presentationHotspots;
|
||||
};
|
||||
|
||||
} // namespace core
|
||||
|
||||
Reference in New Issue
Block a user