22#include <toast/reflect/reflect.hpp>
23#include <unordered_set>
33constexpr std::string_view array_str =
"array_";
34constexpr std::string_view bool_str =
"bool";
35constexpr std::string_view int_str =
"int";
36constexpr std::string_view float_str =
"float";
37constexpr std::string_view string_str =
"string";
38constexpr std::string_view double_str =
"double";
39constexpr std::string_view uid_str =
"uid";
40constexpr std::string_view vec2_str =
"vec2";
41constexpr std::string_view vec3_str =
"vec3";
42constexpr std::string_view vec4_str =
"vec4";
43constexpr std::string_view quaternion_str =
"quat";
45constexpr uint16_t format_version = 4;
48 const std::array<uint8_t, 6> magic = {
'T',
'N',
'O',
'D',
'E',
'\0'};
49 uint16_t version = format_version;
56 enum class Purpose : uint8_t {
66 Prefab(std::istream& file);
73 Prefab(std::span<const uint8_t> bytes);
90 auto type()
const -> std::string_view
override {
105 auto toFile()
const -> std::string;
111 auto toBinary()
const -> std::vector<uint8_t>;
127 static auto stringifyValue(toast::FieldType type,
bool is_array,
const std::any& value) -> std::string;
136 static auto valueFromString(toast::FieldType type,
bool is_array, std::string_view value) -> std::optional<std::any>;
146 toast::FieldType type;
152 auto as()
const -> T {
153 return std::any_cast<T>(value);
165 std::vector<Field> fields;
168 auto find(std::string_view name)
const -> std::optional<Field> {
169 auto it = std::ranges::find_if(fields, [name](
const auto& field) {
return field.name == name; });
170 if (it != fields.end()) {
185 std::vector<Field> fields;
186 std::vector<Subgroup> subgroups;
189 auto find(std::string_view name)
const -> std::optional<Field> {
190 auto it = std::ranges::find_if(fields, [&name](
const auto& field) {
return field.name == name; });
191 if (it != fields.end()) {
194 for (
const auto& g : subgroups) {
195 auto g_it = g.find(name);
196 if (g_it.has_value()) {
216 std::string function;
222 std::vector<SignalConnection> connections;
236 std::vector<Field> fields;
237 std::vector<Group> groups;
242 auto find(std::string_view name)
const -> std::optional<Field> {
243 auto it = std::ranges::find_if(fields, [&name](
const auto& field) {
return field.name == name; });
244 if (it != fields.end()) {
247 for (
const auto& g : groups) {
248 auto g_it = g.find(name);
249 if (g_it.has_value()) {
258 auto findLuaVar(std::string_view path)
const ->
const LuaVarOverride* {
259 auto it = std::ranges::find_if(lua_vars, [&](
const auto& v) {
return v.path == path; });
260 return it != lua_vars.end() ? &*it :
nullptr;
264 std::vector<Field> global_fields;
265 std::vector<BasicNode> nodes;
268 auto parseField(std::string_view line) -> std::optional<Field>;
269 auto parseLuaVarOverride(std::string_view line) -> std::optional<LuaVarOverride>;
270 auto parseSignal(std::string_view line) -> std::optional<Signal>;
271 auto parseType(std::string_view type,
bool& is_array) -> std::optional<toast::FieldType>;
272 auto parseValue(toast::FieldType type, std::string_view value,
bool& is_array) -> std::optional<std::any>;
274 auto parseNodeChunk(std::span<const std::string> lines) -> std::optional<BasicNode>;
275 auto parseGroupChunk(std::span<const std::string> lines) -> std::optional<Group>;
276 auto parseSubgroupChunk(std::span<const std::string> lines) -> std::optional<Subgroup>;
278 void serializeNode(
const toast::Node& node,
bool is_root);
280 void writeNode(
const BasicNode& node, std::stringstream& ss)
const;
281 void writeGroup(
const Group& group, std::stringstream& ss)
const;
282 void writeSubgroup(
const Subgroup& subgroup, std::stringstream& ss)
const;
283 void writeField(
const Field& field, std::stringstream& ss, std::string offset =
"")
const;
284 void writeSignal(
const Signal& signal, std::stringstream& ss)
const;
285 auto writeType(toast::FieldType type,
bool is_array =
false) const -> std::
string;
287 auto fieldEquals(toast::FieldType type,
bool is_array, const std::any& a, const std::any& b) const ->
bool;
288 auto flattenedRootFields(const Handle<Prefab>& source) const -> std::optional<BasicNode>;
290 toast::UID m_self_uid;
291 Purpose m_purpose = Purpose::asset_definition;
292 std::unordered_set<uint64_t>
Inherit from this class to allow an asset to be saved.
Definition core_types.hpp:33
auto toBinary() const -> std::vector< uint8_t >
Serializes to the compact binary format.
Definition prefab.cpp:1121
static auto valueFromString(toast::FieldType type, bool is_array, std::string_view value) -> std::optional< std::any >
Parses a text value back into a typed std::any for a reflected field.
Definition prefab.cpp:776
auto toFile() const -> std::string
Serializes to the human-readable text format.
Definition prefab.cpp:418
Prefab(std::istream &file)
Parses a prefab from a text (.tnode) stream.
Definition prefab.cpp:329
auto serialize(SaveMode mode) const -> std::vector< uint8_t > override
Convenience wrapper that delegates to toFile() or toBinary() based on mode.
Definition prefab.cpp:409
static auto stringifyValue(toast::FieldType type, bool is_array, const std::any &value) -> std::string
Converts a reflected field value to its text representation.
Definition prefab.cpp:1014
auto validate() const -> bool
Checks structural invariants.
Definition prefab.cpp:1791
Base types for the asset system.
SaveMode
Definition core_types.hpp:25
One node entry in a prefab file.
Definition prefab.hpp:232
std::vector< LuaVarOverride > lua_vars
empty for old files or nodes with no edited Lua vars
Definition prefab.hpp:238
std::vector< Signal > signals
empty for old files or nodes with no signal connections
Definition prefab.hpp:239
One field value read from a prefab file.
Definition prefab.hpp:144
A named group of fields and optional subgroups.
Definition prefab.hpp:183
Inspector Lua script variable that differs from its declared default.
Definition prefab.hpp:208
Definition prefab.hpp:214
Definition prefab.hpp:220
A named sub-section of fields within a group.
Definition prefab.hpp:163