843{
844 ReconstructionResult
total;
846
847 const std::string tapestry_path = base_dir + "/tapestry.json";
848 IO::JSONSerializer ser;
849 auto schema_opt = ser.read<State::TapestrySchema>(tapestry_path);
850 if (!schema_opt) {
851 m_last_error =
"Failed to load tapestry schema: " + ser.last_error();
854 }
855 const auto& schema = *schema_opt;
856
857 if (!version_supported(schema.version)) {
861 }
862
863 for (const auto& ref : schema.fabrics) {
864 auto fabric = tapestry.get_fabric(ref.name);
865 if (!fabric) {
866 fabric = tapestry.create_fabric(ref.name,
867 read_cell_size(ref.base_path + ".json").value_or(1.0F));
868 }
870 total.constructed += result.constructed;
871 total.patched += result.patched;
872 total.skipped += result.skipped;
873 for (auto& w : result.warnings) {
874 total.warnings.push_back(ref.name +
": " + std::move(w));
875 }
876 }
877
878 for (const auto& xrec : schema.expanses) {
879 const std::string
label =
"TapestryExpanse '" + xrec.name +
"'";
880 if (!expanse_restorable(xrec,
label,
total.warnings)) {
882 continue;
883 }
884
885 std::vector<Fabric*> fabrics;
886 for (const auto& fname : xrec.fabric_names) {
887 if (auto fabric = tapestry.get_fabric(fname)) {
888 fabrics.push_back(fabric.get());
889 } else {
890 total.warnings.push_back(
label +
": fabric '" + fname +
"' not found");
891 }
892 }
893
894 std::shared_ptr<Expanse> expanse = tapestry.get_expanse(xrec.name);
895 const bool existed = expanse != nullptr;
896
897 if (existed) {
898 apply_bounds(*expanse, xrec);
899 } else {
900 ExpanseParts parts;
901 if (!resolve_expanse_parts(xrec, fabrics,
label, parts,
total.warnings)) {
903 continue;
904 }
905
906 if (xrec.fn_name.empty()) {
907 expanse = tapestry.create_expanse<Expanse>(
908 xrec.name,
909 Kinesis::AABB3D { .min = *xrec.bounds_min, .max = *xrec.bounds_max },
910 std::move(parts.on_enter),
911 std::move(parts.on_exit));
912 } else {
913 expanse = tapestry.create_expanse(
914 xrec.name,
915 std::move(parts.contains),
916 std::move(parts.on_enter),
917 std::move(parts.on_exit));
918 apply_bounds(*expanse, xrec);
919 }
920
921 if (!expanse) {
923 continue;
924 }
925 expanse->set_fn_name(xrec.fn_name);
926 expanse->set_on_enter_fn_name(xrec.on_enter_fn_name);
927 expanse->set_on_exit_fn_name(xrec.on_exit_fn_name);
928 }
929
930 for (Fabric* fabric : fabrics) {
931 fabric->add_expanse(expanse);
932 }
933 if (existed) {
935 } else {
937 }
938 }
939
940 total.user_state = schema.user_state;
941
943 "StateDecoder::reconstruct(Tapestry): constructed={} patched={} skipped={} warnings={}",
946}
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
ReconstructionResult reconstruct(Fabric &fabric, const std::string &base_path)
Patch existing entities and construct missing ones from schema.
@ FileIO
Filesystem I/O operations.
@ Nexus
Spatial indexing and scheduling for user-defined behaviour.