Merge pull request #426 from agnat/serialize_light_refs
KHR_lights_punctual: Serialize node light refs
diff --git a/tiny_gltf.h b/tiny_gltf.h
index 55b17e2..1e757ed 100644
--- a/tiny_gltf.h
+++ b/tiny_gltf.h
@@ -53,10 +53,6 @@
#define TINYGLTF_USE_CPP14
#endif
-#ifndef TINYGLTF_USE_CPP14
-#include <functional>
-#endif
-
#ifdef __ANDROID__
#ifdef TINYGLTF_ANDROID_LOAD_FROM_ASSETS
#include <android/asset_manager.h>
@@ -1736,6 +1732,7 @@
// documents may be active at once.
using json =
rapidjson::GenericValue<rapidjson::UTF8<>, rapidjson::CrtAllocator>;
+using json_iterator = json::MemberIterator;
using json_const_iterator = json::ConstMemberIterator;
using json_const_array_iterator = json const *;
using JsonDocument =
@@ -1747,6 +1744,7 @@
// not thread safe. Only a single JsonDocument may be active at any one time,
// meaning only a single gltf load/save can be active any one time.
using json = rapidjson::Value;
+using json_iterator = json::MemberIterator;
using json_const_iterator = json::ConstMemberIterator;
using json_const_array_iterator = json const *;
rapidjson::Document *s_pActiveDocument = nullptr;
@@ -1793,6 +1791,7 @@
#else
using nlohmann::json;
+using json_iterator = json::iterator;
using json_const_iterator = json::const_iterator;
using json_const_array_iterator = json_const_iterator;
using JsonDocument = json;
@@ -3404,6 +3403,35 @@
#endif
}
+bool FindMember(detail::json &o, const char *member, detail::json_iterator &it) {
+#ifdef TINYGLTF_USE_RAPIDJSON
+ if (!o.IsObject()) {
+ return false;
+ }
+ it = o.FindMember(member);
+ return it != o.MemberEnd();
+#else
+ it = o.find(member);
+ return it != o.end();
+#endif
+}
+
+void Erase(detail::json & o, detail::json_iterator &it) {
+#ifdef TINYGLTF_USE_RAPIDJSON
+ o.EraseMember(it);
+#else
+ o.erase(it);
+#endif
+}
+
+bool IsEmpty(const detail::json & o) {
+#ifdef TINYGLTF_USE_RAPIDJSON
+ return o.ObjectEmpty();
+#else
+ return o.empty();
+#endif
+}
+
const detail::json &GetValue(detail::json_const_iterator &it) {
#ifdef TINYGLTF_USE_RAPIDJSON
return it->value;
@@ -3412,6 +3440,14 @@
#endif
}
+detail::json &GetValue(detail::json_iterator &it) {
+#ifdef TINYGLTF_USE_RAPIDJSON
+ return it->value;
+#else
+ return it.value();
+#endif
+}
+
std::string JsonToString(const detail::json &o, int spacing = -1) {
#ifdef TINYGLTF_USE_RAPIDJSON
using namespace rapidjson;
@@ -7227,6 +7263,42 @@
SerializeExtrasAndExtensions(node, o);
+ // Note(agnat): If the asset was loaded from disk, the node may already
+ // contain the KHR_lights_punctual extension. If it was constructed in
+ // memory it does not. In any case we update the JSON property using
+ // the value from the struct. Last, if the node does not have a light
+ // reference but the extension is still present, we remove it.
+ if (node.light != -1) {
+ detail::json_iterator it;
+ if (!detail::FindMember(o, "extensions", it)) {
+ detail::json extensions;
+ detail::JsonSetObject(extensions);
+ detail::JsonAddMember(o, "extensions", std::move(extensions));
+ detail::FindMember(o, "extensions", it);
+ }
+ auto & extensions = detail::GetValue(it);
+ if ( ! detail::FindMember(extensions, "KHR_lights_punctual", it)) {
+ detail::json lights_punctual;
+ detail::JsonSetObject(lights_punctual);
+ detail::JsonAddMember(extensions, "KHR_lights_punctual", std::move(lights_punctual));
+ detail::FindMember(o, "KHR_lights_punctual", it);
+ }
+ SerializeNumberProperty("light", node.light, detail::GetValue(it));
+ } else {
+ // node has no light ref (any longer)... so we clean up
+ detail::json_iterator ext_it;
+ if (detail::FindMember(o, "extensions", ext_it)) {
+ auto & extensions = detail::GetValue(ext_it);
+ detail::json_iterator lp_it;
+ if (detail::FindMember(extensions, "KHR_lights_punctual", lp_it)) {
+ detail::Erase(extensions, lp_it);
+ }
+ if (detail::IsEmpty(extensions)) {
+ detail::Erase(o, ext_it);
+ }
+ }
+ }
+
if (!node.name.empty()) SerializeStringProperty("name", node.name, o);
SerializeNumberArrayProperty<int>("children", node.children, o);
}