5#include <boost/archive/binary_iarchive.hpp>
6#include <boost/archive/binary_oarchive.hpp>
7#include <boost/archive/text_iarchive.hpp>
8#include <boost/archive/text_oarchive.hpp>
9#include <boost/archive/xml_iarchive.hpp>
10#include <boost/archive/xml_oarchive.hpp>
11#include <boost/archive/yaml_iarchive.hpp>
12#include <boost/archive/yaml_oarchive.hpp>
13#include <boost/serialization/binary_object.hpp>
15#include "sound_bakery/system.h"
16#include "sound_bakery/node/bus/bus.h"
17#include "sound_bakery/core/database/database_object.h"
18#include "sound_bakery/core/object/object_owner.h"
19#include "sound_bakery/event/event.h"
20#include "sound_bakery/sound/sound.h"
21#include "sound_bakery/soundbank/soundbank.h"
34namespace sbk::core::serialization
36 auto make_default_variant(
const rttr::type& type) -> rttr::variant;
37 auto read_binary_file(
const std::filesystem::path& file) -> std::vector<uint8_t>;
46 unsigned int major = SBK_VERSION_MAJOR;
47 unsigned int minor = SBK_VERSION_MINOR;
48 unsigned int patch = SBK_VERSION_PATCH;
50 auto version_compatible()
const ->
bool {
return major == SBK_VERSION_MAJOR && minor == SBK_VERSION_MINOR; }
52 template <
class archive_
class>
53 void serialize(archive_class& archive,
const unsigned int version)
55 archive & boost::serialization::make_nvp(
"Major", major);
56 archive & boost::serialization::make_nvp(
"Minor", minor);
57 archive & boost::serialization::make_nvp(
"Patch", patch);
67 serialized_type(
const rttr::type& type) : typeString(type.get_name().data()) {}
69 std::string typeString;
71 auto get_type()
const -> rttr::type {
return rttr::type::get_by_name(typeString); }
73 template <
class archive_
class>
74 void serialize(archive_class& archive,
const unsigned int fileVersion)
76 archive & boost::serialization::make_nvp(
"Type", typeString);
87 :
object(
object), objectOwner(objectOwner)
91 type.typeString =
object->get_object_type().get_name().data();
92 id =
object->get_database_id();
99 std::shared_ptr<sbk::core::database_object>
object;
102 template <
class archive_
class>
103 void serialize(archive_class& archive,
const unsigned int v)
105 archive & boost::serialization::make_nvp(
"Type", type);
106 archive & boost::serialization::make_nvp(
"ID",
id);
108 if (
typename archive_class::is_loading())
110 BOOST_ASSERT(objectOwner !=
nullptr);
111 std::weak_ptr<sbk::core::database_object> foundObject = sbk::engine::system::get()->try_find(
id);
113 if (foundObject.expired())
116 object->set_flags(object_flag_loading);
120 object = foundObject.lock();
121 objectOwner->add_reference_to_object(
object);
125 BOOST_ASSERT(
object);
126 archive & boost::serialization::make_nvp(
"ObjectData", *
object.get());
128 if (
typename archive_class::is_loading())
130 BOOST_ASSERT(sbk::engine::system::get() !=
nullptr);
131 object->clear_flags(object_flag_loading);
132 sbk::engine::system::get()->add_object_to_database(
object);
146 :
object(
object, objectOwner){}
151 template <
class archive_
class>
152 void serialize(archive_class& archive,
const unsigned int v)
154 archive & boost::serialization::make_nvp(
"Version", version);
155 BOOST_ASSERT_MSG(version.version_compatible(),
"Cross version serialization not implemented yet");
156 archive & boost::serialization::make_nvp(
"Object",
object);
167 template <
class archive_
class>
168 void serialize(archive_class& archive,
const unsigned int v)
171 BOOST_ASSERT(system !=
nullptr);
173 archive & boost::serialization::make_nvp(
"Version", version);
174 BOOST_ASSERT_MSG(version.version_compatible(),
"Cross version serialization not implemented yet");
175 archive & boost::serialization::make_nvp(
"System", *system);
179 template <
class object_
class>
185 : objects(objects), count(objects.size()), objectOwner(
nullptr) {}
188 std::size_t count = 0;
189 std::vector<std::shared_ptr<object_class>> objects;
191 template <
class archive_
class>
192 void serialize(archive_class& archive,
const unsigned int v)
194 archive & boost::serialization::make_nvp(
"Count", count);
196 for (std::size_t index = 0; index < count; ++index)
198 if (
typename archive_class::is_loading())
201 archive & boost::serialization::make_nvp(
"Object", serializedObject);
205 std::shared_ptr<sbk::core::database_object> convertedObject =
206 std::static_pointer_cast<sbk::core::database_object, object_class>(objects[index]);
208 archive & boost::serialization::make_nvp(
"Object", serializedObject);
217 serialized_sound(
const std::shared_ptr<sbk::engine::sound>& sound) : sound(sound) {}
218 serialized_sound(
const std::shared_ptr<sbk::core::database_object>& databaseSound)
219 : sound(std::static_pointer_cast<sbk::engine::sound, sbk::core::database_object>(databaseSound)) {}
221 std::shared_ptr<sbk::engine::sound> sound;
223 template <
class archive_
class>
224 void serialize(archive_class& archive,
const unsigned int v)
228 if (
typename archive_class::is_saving())
231 const std::vector<uint8_t> buffer = read_binary_file(encodingSound.encodedSoundPath);
232 std::size_t size = buffer.size();
234 archive & boost::serialization::make_nvp(
"Size", size);
235 archive & boost::serialization::make_nvp(
"Data", boost::serialization::make_binary_object(buffer.data(), size));
239 std::size_t size = 0;
240 archive & boost::serialization::make_nvp(
"Size", size);
242 sbk::engine::raw_sound_ptr rawSound(std::malloc(size));
243 archive & boost::serialization::make_nvp(
"Data", boost::serialization::make_binary_object(rawSound.get(), size));
245 sound->set_raw_sound_data(rawSound, size);
256 : objects(objects), count(objects.size()), objectOwner(
nullptr)
261 std::size_t count = 0;
262 std::vector<std::shared_ptr<sbk::engine::sound>> objects;
264 template <
class archive_
class>
265 void serialize(archive_class& archive,
const unsigned int v)
267 archive& boost::serialization::make_nvp(
"Count", count);
269 for (std::size_t index = 0; index < count; ++index)
271 if (
typename archive_class::is_loading())
274 archive & boost::serialization::make_nvp(
"Object", serializedObject);
277 archive & boost::serialization::make_nvp(
"RawSound", serializedSound);
282 archive & boost::serialization::make_nvp(
"Object", serializedObject);
285 archive & boost::serialization::make_nvp(
"RawSound", serializedSound);
295 : serializedSoundbank(
object, objectOwner)
302 template <
class archive_
class>
303 void serialize(archive_class& archive,
const unsigned int v)
305 archive & boost::serialization::make_nvp(
"Version", version);
306 BOOST_ASSERT_MSG(version.version_compatible(),
"Cross version serialization not implemented yet");
308 archive & boost::serialization::make_nvp(
"Soundbank", serializedSoundbank);
309 BOOST_ASSERT_MSG(serializedSoundbank.object->get_object_type().is_derived_from<
sbk::engine::soundbank>(),
"Must be saving a soundbank type");
313 if (
typename archive_class::is_loading())
319 archive& boost::serialization::make_nvp(
"Sounds", serializedSounds);
320 archive& boost::serialization::make_nvp(
"Nodes", serializedNodes);
321 archive& boost::serialization::make_nvp(
"Events", serializedEvents);
323 if (soundbank->get_master_soundbank())
330 archive & boost::serialization::make_nvp(
"Busses", serializedBusses);
331 archive & boost::serialization::make_nvp(
"IntParameters", serializedIntParameters);
332 archive & boost::serialization::make_nvp(
"FloatParameters", serializedFloatParameters);
333 archive & boost::serialization::make_nvp(
"NamedParameters", serializedNamedParameters);
344 archive & boost::serialization::make_nvp(
"Sounds", serializedSounds);
345 archive & boost::serialization::make_nvp(
"Nodes", serializedNodes);
346 archive & boost::serialization::make_nvp(
"Events", serializedEvents);
348 if (soundbank->get_master_soundbank())
355 archive & boost::serialization::make_nvp(
"Busses", serializedBusses);
356 archive & boost::serialization::make_nvp(
"IntParameters", serializedIntParameters);
357 archive & boost::serialization::make_nvp(
"FloatParameters", serializedFloatParameters);
358 archive & boost::serialization::make_nvp(
"NamedParameters", serializedNamedParameters);
369 BOOST_ASSERT(variant.is_valid());
370 BOOST_ASSERT(type.is_class());
373 rttr::variant& child;
376 template <
class archive_
class>
377 void serialize(archive_class& archive,
const unsigned int version)
379 for (rttr::property
property : type.get_properties())
382 BOOST_ASSERT(
property.get_type().is_valid());
384 if (
typename archive_class::is_loading())
386 rttr::variant loaded = make_default_variant(
property.get_type());
387 BOOST_ASSERT(loaded.is_valid());
388 archive & boost::serialization::make_nvp(
property.get_name().data(), loaded);
389 loaded.convert(
property.get_type());
390 BOOST_ASSERT(loaded.get_type() ==
property.get_type());
391 property.set_value(child, loaded);
395 rttr::variant variantToSave =
property.get_value(child);
396 archive & boost::serialization::make_nvp(
property.get_name().data(), variantToSave);
406 : originalVariant(variant), view(variant.create_sequential_view()), valueType(view.get_value_type())
410 rttr::variant& originalVariant;
411 rttr::variant_sequential_view view;
412 rttr::type valueType;
414 template <
class archive_
class>
415 void serialize(archive_class& archive,
const unsigned int version)
417 if (
typename archive_class::is_loading())
420 archive & boost::serialization::make_nvp(
"Count", size);
424 const bool needToCreate = size == 0;
426 for (
size_t index = 0; index < size; ++index)
428 rttr::variant loadedVariant = make_default_variant(valueType);
429 BOOST_ASSERT(loadedVariant.is_valid());
430 archive & boost::serialization::make_nvp(
"Item", loadedVariant);
432 loadedVariant.convert((rttr::type)valueType);
435 view.insert(view.begin() + index, loadedVariant);
439 view.set_value(index, loadedVariant);
445 size_t size = view.get_size();
446 archive & boost::serialization::make_nvp(
"Count", size);
448 for (rttr::variant item : view)
450 archive & boost::serialization::make_nvp(
"Item", item);
460 : originalVariant(variant),
461 view(variant.create_associative_view()),
462 keyType(view.get_key_type()),
463 valueType(view.is_key_only_type() ? view.get_key_type()
464 : view.get_value_type())
467 rttr::variant& originalVariant;
468 rttr::variant_associative_view view;
469 rttr::type valueType;
472 template <
class archive_
class>
473 void serialize(archive_class& archive,
const unsigned int version)
475 if (
typename archive_class::is_loading())
478 archive& boost::serialization::make_nvp(
"Count", size);
482 for (std::size_t index = 0; index < size; ++index)
484 if (view.is_key_only_type())
486 rttr::variant loadedKey = make_default_variant(keyType);
487 archive & boost::serialization::make_nvp(
"Key", loadedKey);
488 loadedKey.convert((rttr::type)keyType);
489 view.insert(loadedKey);
493 std::pair<rttr::variant, rttr::variant> loadedPair(make_default_variant(keyType), make_default_variant(valueType));
494 archive & boost::serialization::make_nvp(
"KeyValue", loadedPair);
495 loadedPair.first.convert((rttr::type)keyType);
496 loadedPair.second.convert((rttr::type)valueType);
497 view.insert(loadedPair.first, loadedPair.second);
503 size_t size = view.get_size();
504 archive & boost::serialization::make_nvp(
"Count", size);
506 for (rttr::variant item : view)
508 std::pair<rttr::variant, rttr::variant> valuePair =
509 item.convert<std::pair<rttr::variant, rttr::variant>>();
511 if (view.is_key_only_type())
513 rttr::variant key = valuePair.first.extract_wrapped_value();
514 archive & boost::serialization::make_nvp(
"Key", key);
518 archive& boost::serialization::make_nvp(
"KeyValue", valuePair);
525 template <
class load_archive,
527 std::ios_base::openmode inputMode,
528 std::ios_base::openmode outputMode>
532 template <
class serialize_
class>
533 auto save_database_object(std::shared_ptr<sbk::core::database_object>&
object,
const std::filesystem::path& file) -> sb_result
535 SC_CHECK_ARG(
object);
536 SC_CHECK(!file.empty(), MA_INVALID_FILE);
538 std::ofstream outputStream(file, outputMode);
539 save_archive archive(outputStream);
540 serialize_class serialize(
object,
nullptr);
542 archive & boost::serialization::make_nvp(
"Data", serialize);
546 auto save_system(
const std::filesystem::path& file) -> sb_result
548 SC_CHECK(!file.empty(), MA_INVALID_FILE);
550 std::ofstream outputStream(file, outputMode);
551 save_archive archive(outputStream);
554 archive & boost::serialization::make_nvp(
"System", serialize);
558 template <
class serialize_
class>
561 SC_CHECK(std::filesystem::exists(file), MA_INVALID_FILE);
563 std::ifstream inputStream(file, inputMode);
564 load_archive archive(inputStream);
565 serialize_class
object({}, objectOwner);
567 archive & boost::serialization::make_nvp(
"Data",
object);
582 namespace serialization
584 template <
class archive_
class,
typename T>
585 void serialize_variant(archive_class& archive, rttr::variant& variant)
587 if (
typename archive_class::is_loading())
590 archive & boost::serialization::make_nvp(
"Value", loadedValue);
591 variant = loadedValue;
595 T valueToSave = variant.convert<T>();
596 archive & boost::serialization::make_nvp(
"Value", valueToSave);
600 template <
class archive_
class>
601 void serialize_variant_string_view(archive_class& archive, rttr::variant& variant)
603 if (
typename archive_class::is_loading())
606 archive & boost::serialization::make_nvp(
"Value", loaded);
611 std::string_view valueToSave = variant.convert<std::string_view>();
612 std::string valueToSaveConverted(valueToSave);
613 archive & boost::serialization::make_nvp(
"Value", valueToSaveConverted);
617 template <
class archive_
class>
618 void serialize(archive_class& archive, rttr::variant& variant,
const unsigned int version)
620 const rttr::type type = variant.get_type();
621 BOOST_ASSERT_MSG(type.is_valid(),
"Type must be valid to load correctly");
623 if (type.is_arithmetic())
625 if (type == rttr::type::get<bool>())
627 serialize_variant<archive_class, bool>(archive, variant);
629 else if (type == rttr::type::get<int8_t>())
631 serialize_variant<archive_class, int8_t>(archive, variant);
633 else if (type == rttr::type::get<int16_t>())
635 serialize_variant<archive_class, int16_t>(archive, variant);
637 else if (type == rttr::type::get<int32_t>())
639 serialize_variant<archive_class, int32_t>(archive, variant);
641 else if (type == rttr::type::get<int64_t>())
643 serialize_variant<archive_class, int64_t>(archive, variant);
645 else if (type == rttr::type::get<uint8_t>())
647 serialize_variant<archive_class, uint8_t>(archive, variant);
649 else if (type == rttr::type::get<uint16_t>())
651 serialize_variant<archive_class, uint16_t>(archive, variant);
653 else if (type == rttr::type::get<uint32_t>())
655 serialize_variant<archive_class, uint32_t>(archive, variant);
657 else if (type == rttr::type::get<uint64_t>())
659 serialize_variant<archive_class, uint64_t>(archive, variant);
661 else if (type == rttr::type::get<float>())
663 serialize_variant<archive_class, float>(archive, variant);
665 else if (type == rttr::type::get<double>())
667 serialize_variant<archive_class, double>(archive, variant);
670 else if (type == rttr::type::get<std::string>())
672 serialize_variant<archive_class, std::string>(archive, variant);
674 else if (type == rttr::type::get<std::string_view>())
676 serialize_variant_string_view<archive_class>(archive, variant);
678 else if (type.is_wrapper())
680 variant = variant.extract_wrapped_value();
681 serialize(archive, variant, version);
683 else if (type.is_enumeration())
685 const rttr::enumeration enumeration = type.get_enumeration();
687 if (
typename archive_class::is_loading())
689 std::string loadedStringValue;
690 archive& boost::serialization::make_nvp(
"Value", loadedStringValue);
691 variant = enumeration.name_to_value(loadedStringValue);
695 const rttr::string_view enumValueName = enumeration.value_to_name(variant);
697 if (!enumValueName.empty())
699 std::string savingString = enumValueName.data();
700 archive& boost::serialization::make_nvp(
"Value", savingString);
704 else if (type.is_associative_container())
707 archive & boost::serialization::make_nvp(
"AssociativeContainer", serializedAssociativeContainer);
709 else if (type.is_sequential_container())
712 archive & boost::serialization::make_nvp(
"SeqContainer", serializedSequentialContainer);
714 else if (type.is_class())
717 archive & boost::serialization::make_nvp(
"Child", childClass);
Creates, owns and tracks objects.
Definition object_owner.h:13
auto create_database_object(const rttr::type &type, bool addToDatabase=true) -> std::shared_ptr< database_object >
Definition object_owner.cpp:74
Base object that all sound Bakery objects should inherit from.
Definition object.h:23
Definition serializer.h:530
Packages events and dependent objects and sounds.
Definition soundbank.h:35
Manager of the whole Sound Bakery.
Definition system.h:44
Definition serializer.h:457
Definition serializer.h:365
Definition serializer.h:181
Serializes an object type and the object's data.
Definition serializer.h:84
Definition serializer.h:403
Definition serializer.h:215
Definition serializer.h:292
Header for an object that saves to a single file.
Definition serializer.h:143
Definition serializer.h:161
Serializes an object type so upon loading, we create the correct type.
Definition serializer.h:65
Stores the version of Sound Bakery.
Definition serializer.h:45
Data for converting a sound to an encoded format.
Definition sound.h:15
Wraps all events, objects, and sounds needed to package a soundbank.
Definition soundbank.h:20