-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFrameAnimationMsgPack.cpp
More file actions
157 lines (136 loc) · 5.73 KB
/
Copy pathFrameAnimationMsgPack.cpp
File metadata and controls
157 lines (136 loc) · 5.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include "FrameAnimationMsgPack.h"
#include "FrameAnimationData.h"
#include "DekiLogSystem.h"
#include "assets/AssetManager.h"
#include "PrefabMessagePack.h"
#include <cstddef>
#include <cstdint>
#include <fstream>
#include <vector>
#ifdef DEKI_EDITOR
// Editor-only: save serializes through the generated reflection serializer.
#include <nlohmann/json.hpp>
#include "reflection/Serialization.h"
using json = nlohmann::json;
#endif
// FrameAnimationData is a DEKI_SERIALIZABLE struct, so the reflection codegen
// generates both the editor JSON Serialize<T> and the all-platforms
// DeserializeMsgPack (declared via generated/FrameAnimationData.gen.h, included
// by FrameAnimationData.h). Load and save go through those generated functions,
// so there is no hand-written per-field parsing here, on desktop or on device.
bool FrameAnimationMsgPackHelper::LoadAnimation(const char* msgpack_path, FrameAnimationData* out_data)
{
if (!msgpack_path || !out_data)
{
DEKI_LOG_ERROR("FrameAnimationMsgPackHelper::LoadAnimation - null parameters");
return false;
}
// Read file into buffer
std::ifstream file(msgpack_path, std::ios::binary | std::ios::ate);
if (!file.is_open())
{
DEKI_LOG_ERROR("FrameAnimationMsgPackHelper::LoadAnimation - failed to open: %s", msgpack_path);
return false;
}
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<uint8_t> buffer(size);
if (!file.read(reinterpret_cast<char*>(buffer.data()), size))
{
DEKI_LOG_ERROR("FrameAnimationMsgPackHelper::LoadAnimation - failed to read file");
return false;
}
return LoadAnimationFromMemory(buffer.data(), static_cast<size_t>(size), out_data);
}
bool FrameAnimationMsgPackHelper::LoadAnimationFromMemory(const uint8_t* data, size_t size, FrameAnimationData* out_data)
{
if (!data || size == 0 || !out_data)
{
DEKI_LOG_ERROR("FrameAnimationMsgPackHelper::LoadAnimationFromMemory - invalid parameters");
return false;
}
out_data->spritesheet_guid.clear();
out_data->animations.clear();
// Generated, reflection-driven MessagePack deserialize (full field-name keys).
// Identical path on desktop and embedded via PrefabMsgPackParser.
PrefabFormat::PrefabMsgPackParser parser(data, size);
uint32_t mapSize = 0;
if (!parser.ReadMapSize(mapSize))
{
DEKI_LOG_ERROR("FrameAnimationMsgPackHelper::LoadAnimationFromMemory - root is not a MessagePack map");
return false;
}
if (!DeserializeMsgPack(*out_data, parser, mapSize))
{
DEKI_LOG_ERROR("FrameAnimationMsgPackHelper::LoadAnimationFromMemory - deserialize failed");
return false;
}
int totalFrames = 0;
for (const auto& anim : out_data->animations)
totalFrames += static_cast<int>(anim.frames.size());
DEKI_LOG_INTERNAL("FrameAnimationMsgPackHelper::LoadAnimation - loaded %d animations with %d total frames",
static_cast<int>(out_data->animations.size()), totalFrames);
return true;
}
#ifdef DEKI_EDITOR
bool FrameAnimationMsgPackHelper::SaveAnimation(const char* msgpack_path, const FrameAnimationData* anim_data)
{
if (!msgpack_path || !anim_data)
{
DEKI_LOG_ERROR("FrameAnimationMsgPackHelper::SaveAnimation - null parameters");
return false;
}
try
{
// Generated reflection serialize (full field-name keys) -> MessagePack.
// Mirrors the load path; nested sequences/frames are handled recursively.
json j = Serialize<FrameAnimationData>(*anim_data);
std::vector<uint8_t> msgpack_data = json::to_msgpack(j);
std::ofstream file(msgpack_path, std::ios::binary);
if (!file.is_open())
{
DEKI_LOG_ERROR("FrameAnimationMsgPackHelper::SaveAnimation - failed to open for writing: %s", msgpack_path);
return false;
}
file.write(reinterpret_cast<const char*>(msgpack_data.data()), msgpack_data.size());
int totalFrames = 0;
for (const auto& seq : anim_data->animations)
totalFrames += static_cast<int>(seq.frames.size());
DEKI_LOG_INTERNAL("FrameAnimationMsgPackHelper::SaveAnimation - saved %d animations with %d total frames (%zu bytes)",
static_cast<int>(anim_data->animations.size()), totalFrames, msgpack_data.size());
return file.good();
}
catch (const std::exception& e)
{
DEKI_LOG_ERROR("FrameAnimationMsgPackHelper::SaveAnimation - error: %s", e.what());
return false;
}
}
#endif
// Self-register animation loader with AssetManager. The memLoader lets packed
// animations load straight from a .dpack on device (previously missing, so packed
// animations could only load as loose cache files).
namespace {
struct _AnimLoaderReg {
_AnimLoaderReg() {
auto loader = [](const char* p) -> void* {
auto* data = new FrameAnimationData();
if (FrameAnimationMsgPackHelper::LoadAnimation(p, data))
return data;
delete data;
return nullptr;
};
auto unloader = [](void* a) { delete static_cast<FrameAnimationData*>(a); };
auto memLoader = [](const uint8_t* d, size_t n) -> void* {
auto* data = new FrameAnimationData();
if (FrameAnimationMsgPackHelper::LoadAnimationFromMemory(d, n, data))
return data;
delete data;
return nullptr;
};
Deki::AssetManager::RegisterLoader("FrameAnimationData", loader, unloader, memLoader);
Deki::AssetManager::RegisterLoader("Animation", loader, unloader, memLoader);
}
};
static _AnimLoaderReg s_animLoaderReg;
}