Files
hfut-bishe/client/core/library/EntityJson.cpp

306 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "library/EntityJson.h"
#include <functional>
#include <QJsonArray>
#include <QJsonValue>
namespace core::library {
namespace {
QJsonArray pointToJson(const QPointF& p) {
return QJsonArray{p.x(), p.y()};
}
bool pointFromJson(const QJsonValue& v, QPointF& out) {
if (!v.isArray()) {
return false;
}
const QJsonArray a = v.toArray();
if (a.size() < 2) {
return false;
}
out = QPointF(a.at(0).toDouble(), a.at(1).toDouble());
return true;
}
QJsonArray pointsToJson(const QVector<QPointF>& pts) {
QJsonArray a;
for (const auto& p : pts) {
a.append(pointToJson(p));
}
return a;
}
bool pointsFromJson(const QJsonValue& v, QVector<QPointF>& out) {
out.clear();
if (!v.isArray()) {
return false;
}
const QJsonArray a = v.toArray();
out.reserve(a.size());
for (const auto& it : a) {
QPointF p;
if (!pointFromJson(it, p)) {
return false;
}
out.push_back(p);
}
return true;
}
template <class T>
QJsonArray vecToJson(const QVector<T>& v, const std::function<QJsonObject(const T&)>& fn) {
QJsonArray a;
for (const auto& x : v) {
a.append(fn(x));
}
return a;
}
} // namespace
QJsonObject entityToJson(const core::Project::Entity& e) {
QJsonObject o;
o.insert(QStringLiteral("id"), e.id);
o.insert(QStringLiteral("displayName"), e.displayName);
o.insert(QStringLiteral("visible"), e.visible);
o.insert(QStringLiteral("polygonLocal"), pointsToJson(e.polygonLocal));
o.insert(QStringLiteral("cutoutPolygonWorld"), pointsToJson(e.cutoutPolygonWorld));
o.insert(QStringLiteral("originWorld"), pointToJson(e.originWorld));
o.insert(QStringLiteral("depth"), e.depth);
o.insert(QStringLiteral("imagePath"), e.imagePath);
o.insert(QStringLiteral("imageTopLeftWorld"), pointToJson(e.imageTopLeftWorld));
o.insert(QStringLiteral("userScale"), e.userScale);
o.insert(QStringLiteral("distanceScaleCalibMult"), e.distanceScaleCalibMult);
o.insert(QStringLiteral("ignoreDistanceScale"), e.ignoreDistanceScale);
o.insert(QStringLiteral("parentId"), e.parentId);
o.insert(QStringLiteral("parentOffsetWorld"), pointToJson(e.parentOffsetWorld));
o.insert(QStringLiteral("entityPayloadPath"), e.entityPayloadPath);
o.insert(QStringLiteral("legacyAnimSidecarPath"), e.legacyAnimSidecarPath);
o.insert(QStringLiteral("locationKeys"),
vecToJson<core::Project::Entity::KeyframeVec2>(
e.locationKeys, [](const core::Project::Entity::KeyframeVec2& k) {
QJsonObject ko;
ko.insert(QStringLiteral("frame"), k.frame);
ko.insert(QStringLiteral("value"), pointToJson(k.value));
return ko;
}));
o.insert(QStringLiteral("depthScaleKeys"),
vecToJson<core::Project::Entity::KeyframeFloat01>(
e.depthScaleKeys, [](const core::Project::Entity::KeyframeFloat01& k) {
QJsonObject ko;
ko.insert(QStringLiteral("frame"), k.frame);
ko.insert(QStringLiteral("value"), k.value);
return ko;
}));
o.insert(QStringLiteral("userScaleKeys"),
vecToJson<core::Project::Entity::KeyframeDouble>(
e.userScaleKeys, [](const core::Project::Entity::KeyframeDouble& k) {
QJsonObject ko;
ko.insert(QStringLiteral("frame"), k.frame);
ko.insert(QStringLiteral("value"), k.value);
return ko;
}));
o.insert(QStringLiteral("imageFrames"),
vecToJson<core::Project::Entity::ImageFrame>(
e.imageFrames, [](const core::Project::Entity::ImageFrame& k) {
QJsonObject ko;
ko.insert(QStringLiteral("frame"), k.frame);
ko.insert(QStringLiteral("imagePath"), k.imagePath);
return ko;
}));
o.insert(QStringLiteral("visibilityKeys"),
vecToJson<core::Project::ToolKeyframeBool>(
e.visibilityKeys, [](const core::Project::ToolKeyframeBool& k) {
QJsonObject ko;
ko.insert(QStringLiteral("frame"), k.frame);
ko.insert(QStringLiteral("value"), k.value);
return ko;
}));
{
QJsonObject intro;
intro.insert(QStringLiteral("title"), e.intro.title);
intro.insert(QStringLiteral("bodyText"), e.intro.bodyText);
QJsonArray imgs;
for (const auto& p : e.intro.imagePathsRelative) {
imgs.append(p);
}
intro.insert(QStringLiteral("imagePathsRelative"), imgs);
intro.insert(QStringLiteral("videoPathRelative"), e.intro.videoPathRelative);
o.insert(QStringLiteral("intro"), intro);
}
return o;
}
bool entityFromJson(const QJsonObject& o, core::Project::Entity& out) {
core::Project::Entity e;
e.id = o.value(QStringLiteral("id")).toString();
e.displayName = o.value(QStringLiteral("displayName")).toString();
e.visible = o.value(QStringLiteral("visible")).toBool(true);
if (!pointsFromJson(o.value(QStringLiteral("polygonLocal")), e.polygonLocal)) {
return false;
}
if (!pointsFromJson(o.value(QStringLiteral("cutoutPolygonWorld")), e.cutoutPolygonWorld)) {
// cutout 允许不存在:按空处理
e.cutoutPolygonWorld.clear();
}
{
QPointF p;
if (!pointFromJson(o.value(QStringLiteral("originWorld")), p)) {
p = QPointF();
}
e.originWorld = p;
}
e.depth = o.value(QStringLiteral("depth")).toInt(0);
e.imagePath = o.value(QStringLiteral("imagePath")).toString();
{
QPointF p;
if (!pointFromJson(o.value(QStringLiteral("imageTopLeftWorld")), p)) {
p = QPointF();
}
e.imageTopLeftWorld = p;
}
e.userScale = o.value(QStringLiteral("userScale")).toDouble(1.0);
e.distanceScaleCalibMult = o.value(QStringLiteral("distanceScaleCalibMult")).toDouble(0.0);
e.ignoreDistanceScale = o.value(QStringLiteral("ignoreDistanceScale")).toBool(false);
e.parentId = o.value(QStringLiteral("parentId")).toString();
{
QPointF p;
if (!pointFromJson(o.value(QStringLiteral("parentOffsetWorld")), p)) {
p = QPointF();
}
e.parentOffsetWorld = p;
}
e.entityPayloadPath = o.value(QStringLiteral("entityPayloadPath")).toString();
e.legacyAnimSidecarPath = o.value(QStringLiteral("legacyAnimSidecarPath")).toString();
auto parseKeyframesVec2 = [&](const QString& key, QVector<core::Project::Entity::KeyframeVec2>& dst) -> bool {
dst.clear();
const QJsonValue v = o.value(key);
if (!v.isArray()) {
return true;
}
const QJsonArray a = v.toArray();
dst.reserve(a.size());
for (const auto& it : a) {
if (!it.isObject()) return false;
const QJsonObject ko = it.toObject();
core::Project::Entity::KeyframeVec2 k;
k.frame = ko.value(QStringLiteral("frame")).toInt(0);
QPointF pv;
if (!pointFromJson(ko.value(QStringLiteral("value")), pv)) {
return false;
}
k.value = pv;
dst.push_back(k);
}
return true;
};
auto parseKeyframesFloat01 = [&](const QString& key, QVector<core::Project::Entity::KeyframeFloat01>& dst) -> bool {
dst.clear();
const QJsonValue v = o.value(key);
if (!v.isArray()) {
return true;
}
const QJsonArray a = v.toArray();
dst.reserve(a.size());
for (const auto& it : a) {
if (!it.isObject()) return false;
const QJsonObject ko = it.toObject();
core::Project::Entity::KeyframeFloat01 k;
k.frame = ko.value(QStringLiteral("frame")).toInt(0);
k.value = ko.value(QStringLiteral("value")).toDouble(0.5);
dst.push_back(k);
}
return true;
};
auto parseKeyframesDouble = [&](const QString& key, QVector<core::Project::Entity::KeyframeDouble>& dst) -> bool {
dst.clear();
const QJsonValue v = o.value(key);
if (!v.isArray()) {
return true;
}
const QJsonArray a = v.toArray();
dst.reserve(a.size());
for (const auto& it : a) {
if (!it.isObject()) return false;
const QJsonObject ko = it.toObject();
core::Project::Entity::KeyframeDouble k;
k.frame = ko.value(QStringLiteral("frame")).toInt(0);
k.value = ko.value(QStringLiteral("value")).toDouble(1.0);
dst.push_back(k);
}
return true;
};
auto parseImageFrames = [&](const QString& key, QVector<core::Project::Entity::ImageFrame>& dst) -> bool {
dst.clear();
const QJsonValue v = o.value(key);
if (!v.isArray()) {
return true;
}
const QJsonArray a = v.toArray();
dst.reserve(a.size());
for (const auto& it : a) {
if (!it.isObject()) return false;
const QJsonObject ko = it.toObject();
core::Project::Entity::ImageFrame k;
k.frame = ko.value(QStringLiteral("frame")).toInt(0);
k.imagePath = ko.value(QStringLiteral("imagePath")).toString();
dst.push_back(k);
}
return true;
};
if (!parseKeyframesVec2(QStringLiteral("locationKeys"), e.locationKeys)) return false;
if (!parseKeyframesFloat01(QStringLiteral("depthScaleKeys"), e.depthScaleKeys)) return false;
if (!parseKeyframesDouble(QStringLiteral("userScaleKeys"), e.userScaleKeys)) return false;
if (!parseImageFrames(QStringLiteral("imageFrames"), e.imageFrames)) return false;
// visibilityKeys可缺省默认永远可见
e.visibilityKeys.clear();
if (o.value(QStringLiteral("visibilityKeys")).isArray()) {
const QJsonArray a = o.value(QStringLiteral("visibilityKeys")).toArray();
e.visibilityKeys.reserve(a.size());
for (const auto& it : a) {
if (!it.isObject()) return false;
const QJsonObject ko = it.toObject();
core::Project::ToolKeyframeBool k;
k.frame = ko.value(QStringLiteral("frame")).toInt(0);
k.value = ko.value(QStringLiteral("value")).toBool(true);
e.visibilityKeys.push_back(k);
}
}
if (o.contains(QStringLiteral("intro")) && o.value(QStringLiteral("intro")).isObject()) {
const QJsonObject intro = o.value(QStringLiteral("intro")).toObject();
e.intro.title = intro.value(QStringLiteral("title")).toString();
e.intro.bodyText = intro.value(QStringLiteral("bodyText")).toString();
e.intro.videoPathRelative = intro.value(QStringLiteral("videoPathRelative")).toString();
e.intro.imagePathsRelative.clear();
if (intro.value(QStringLiteral("imagePathsRelative")).isArray()) {
const QJsonArray imgs = intro.value(QStringLiteral("imagePathsRelative")).toArray();
e.intro.imagePathsRelative.reserve(imgs.size());
for (const auto& iv : imgs) {
e.intro.imagePathsRelative.push_back(iv.toString());
}
}
}
out = e;
return true;
}
} // namespace core::library