Added 'warning' message parameter to glTF loader API.
Asset loading failure messages(e.g. image file is missing) are now stored in `warning` message, not `error` message.
diff --git a/tiny_gltf.h b/tiny_gltf.h
index 2ad7385..633f4b3 100644
--- a/tiny_gltf.h
+++ b/tiny_gltf.h
@@ -599,7 +599,7 @@
// when rendering.
int indices; // The index of the accessor that contains the indices.
int mode; // one of TINYGLTF_MODE_***
- std::vector<std::map<std::string, int> > targets; // array of morph targets,
+ std::vector<std::map<std::string, int>> targets; // array of morph targets,
// where each target is a dict with attribues in ["POSITION, "NORMAL",
// "TANGENT"] pointing
// to their corresponding accessors
@@ -615,7 +615,7 @@
std::string name;
std::vector<Primitive> primitives;
std::vector<double> weights; // weights to be applied to the Morph Targets
- std::vector<std::map<std::string, int> > targets;
+ std::vector<std::map<std::string, int>> targets;
ExtensionMap extensions;
Value extras;
};
@@ -734,8 +734,9 @@
///
/// LoadImageDataFunction type. Signature for custom image loading callbacks.
///
-typedef bool (*LoadImageDataFunction)(Image *, std::string *, int, int,
- const unsigned char *, int, void *);
+typedef bool (*LoadImageDataFunction)(Image *, std::string *, std::string *,
+ int, int, const unsigned char *, int,
+ void *);
///
/// WriteImageDataFunction type. Signature for custom image writing callbacks.
@@ -745,9 +746,9 @@
#ifndef TINYGLTF_NO_STB_IMAGE
// Declaration of default image loader callback
-bool LoadImageData(Image *image, std::string *err, int req_width,
- int req_height, const unsigned char *bytes, int size,
- void *);
+bool LoadImageData(Image *image, std::string *err, std::string *warn,
+ int req_width, int req_height, const unsigned char *bytes,
+ int size, void *);
#endif
#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
@@ -759,28 +760,24 @@
///
/// FilExistsFunction type. Signature for custom filesystem callbacks.
///
-typedef bool (*FileExistsFunction)(const std::string &abs_filename,
- void *);
+typedef bool (*FileExistsFunction)(const std::string &abs_filename, void *);
///
/// ExpandFilePathFunction type. Signature for custom filesystem callbacks.
///
-typedef std::string (*ExpandFilePathFunction)(const std::string &,
- void *);
+typedef std::string (*ExpandFilePathFunction)(const std::string &, void *);
///
/// ReadWholeFileFunction type. Signature for custom filesystem callbacks.
///
typedef bool (*ReadWholeFileFunction)(std::vector<unsigned char> *,
- std::string *,
- const std::string &,
+ std::string *, const std::string &,
void *);
///
/// WriteWholeFileFunction type. Signature for custom filesystem callbacks.
///
-typedef bool (*WriteWholeFileFunction)(std::string *,
- const std::string &,
+typedef bool (*WriteWholeFileFunction)(std::string *, const std::string &,
const std::vector<unsigned char> &,
void *);
@@ -788,33 +785,27 @@
/// A structure containing all required filesystem callbacks and a pointer to
/// their user data.
///
-struct FsCallbacks
-{
- FileExistsFunction FileExists;
- ExpandFilePathFunction ExpandFilePath;
- ReadWholeFileFunction ReadWholeFile;
- WriteWholeFileFunction WriteWholeFile;
+struct FsCallbacks {
+ FileExistsFunction FileExists;
+ ExpandFilePathFunction ExpandFilePath;
+ ReadWholeFileFunction ReadWholeFile;
+ WriteWholeFileFunction WriteWholeFile;
- void* user_data; // An argument that is passed to all fs callbacks
+ void *user_data; // An argument that is passed to all fs callbacks
};
#ifndef TINYGLTF_NO_FS
// Declaration of default filesystem callbacks
-bool FileExists(const std::string &abs_filename,
- void *);
+bool FileExists(const std::string &abs_filename, void *);
-std::string ExpandFilePath(const std::string &filepath,
- void *);
+std::string ExpandFilePath(const std::string &filepath, void *);
bool ReadWholeFile(std::vector<unsigned char> *out, std::string *err,
- const std::string &filepath,
- void *);
+ const std::string &filepath, void *);
-bool WriteWholeFile(std::string *err,
- const std::string &filepath,
- const std::vector<unsigned char> &contents,
- void *);
+bool WriteWholeFile(std::string *err, const std::string &filepath,
+ const std::vector<unsigned char> &contents, void *);
#endif
class TinyGLTF {
@@ -834,36 +825,40 @@
///
/// Loads glTF ASCII asset from a file.
+ /// Set warning message to `warn` for example it fails to load asserts.
/// Returns false and set error string to `err` if there's an error.
///
- bool LoadASCIIFromFile(Model *model, std::string *err,
+ bool LoadASCIIFromFile(Model *model, std::string *err, std::string *warn,
const std::string &filename,
unsigned int check_sections = REQUIRE_ALL);
///
/// Loads glTF ASCII asset from string(memory).
/// `length` = strlen(str);
+ /// Set warning message to `warn` for example it fails to load asserts.
/// Returns false and set error string to `err` if there's an error.
///
- bool LoadASCIIFromString(Model *model, std::string *err, const char *str,
- const unsigned int length,
+ bool LoadASCIIFromString(Model *model, std::string *err, std::string *warn,
+ const char *str, const unsigned int length,
const std::string &base_dir,
unsigned int check_sections = REQUIRE_ALL);
///
/// Loads glTF binary asset from a file.
+ /// Set warning message to `warn` for example it fails to load asserts.
/// Returns false and set error string to `err` if there's an error.
///
- bool LoadBinaryFromFile(Model *model, std::string *err,
+ bool LoadBinaryFromFile(Model *model, std::string *err, std::string *warn,
const std::string &filename,
unsigned int check_sections = REQUIRE_ALL);
///
/// Loads glTF binary asset from memory.
/// `length` = strlen(str);
+ /// Set warning message to `warn` for example it fails to load asserts.
/// Returns false and set error string to `err` if there's an error.
///
- bool LoadBinaryFromMemory(Model *model, std::string *err,
+ bool LoadBinaryFromMemory(Model *model, std::string *err, std::string *warn,
const unsigned char *bytes,
const unsigned int length,
const std::string &base_dir = "",
@@ -895,11 +890,12 @@
///
/// Loads glTF asset from string(memory).
/// `length` = strlen(str);
+ /// Set warning message to `warn` for example it fails to load asserts
/// Returns false and set error string to `err` if there's an error.
///
- bool LoadFromString(Model *model, std::string *err, const char *str,
- const unsigned int length, const std::string &base_dir,
- unsigned int check_sections);
+ bool LoadFromString(Model *model, std::string *err, std::string *warn,
+ const char *str, const unsigned int length,
+ const std::string &base_dir, unsigned int check_sections);
const unsigned char *bin_data_;
size_t bin_size_;
@@ -907,38 +903,32 @@
FsCallbacks fs = {
#ifndef TINYGLTF_NO_FS
- &tinygltf::FileExists,
- &tinygltf::ExpandFilePath,
- &tinygltf::ReadWholeFile,
- &tinygltf::WriteWholeFile,
+ &tinygltf::FileExists, &tinygltf::ExpandFilePath,
+ &tinygltf::ReadWholeFile, &tinygltf::WriteWholeFile,
- nullptr // Fs callback user data
+ nullptr // Fs callback user data
#else
- nullptr,
- nullptr,
- nullptr,
- nullptr,
+ nullptr, nullptr, nullptr, nullptr,
- nullptr // Fs callback user data
+ nullptr // Fs callback user data
#endif
};
LoadImageDataFunction LoadImageData =
#ifndef TINYGLTF_NO_STB_IMAGE
- &tinygltf::LoadImageData;
+ &tinygltf::LoadImageData;
#else
- nullptr;
+ nullptr;
#endif
- void *load_image_user_data_ = reinterpret_cast<void *>(&fs);
+ void *load_image_user_data_ = reinterpret_cast<void *>(&fs);
WriteImageDataFunction WriteImageData =
#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
- &tinygltf::WriteImageData;
+ &tinygltf::WriteImageData;
#else
- nullptr;
+ nullptr;
#endif
void *write_image_user_data_ = reinterpret_cast<void *>(&fs);
-
};
#ifdef __clang__
@@ -1071,19 +1061,16 @@
}
static std::string FindFile(const std::vector<std::string> &paths,
- const std::string &filepath,
- FsCallbacks* fs) {
-
+ const std::string &filepath, FsCallbacks *fs) {
if (fs == nullptr || fs->ExpandFilePath == nullptr ||
fs->FileExists == nullptr) {
-
// Error, fs callback[s] missing
return std::string();
}
for (size_t i = 0; i < paths.size(); i++) {
- std::string absPath = fs->ExpandFilePath(JoinPath(paths[i], filepath),
- fs->user_data);
+ std::string absPath =
+ fs->ExpandFilePath(JoinPath(paths[i], filepath), fs->user_data);
if (fs->FileExists(absPath, fs->user_data)) {
return absPath;
}
@@ -1245,14 +1232,11 @@
#endif
static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
- const std::string &filename,
+ std::string *warn, const std::string &filename,
const std::string &basedir, size_t reqBytes,
- bool checkSize,
- FsCallbacks *fs) {
-
- if (fs == nullptr || fs->FileExists == nullptr
- || fs->ExpandFilePath == nullptr || fs->ReadWholeFile == nullptr) {
-
+ bool checkSize, FsCallbacks *fs) {
+ if (fs == nullptr || fs->FileExists == nullptr ||
+ fs->ExpandFilePath == nullptr || fs->ReadWholeFile == nullptr) {
// This is a developer error, assert() ?
if (err) {
(*err) += "FS callback[s] not set\n";
@@ -1268,16 +1252,16 @@
std::string filepath = FindFile(paths, filename, fs);
if (filepath.empty() || filename.empty()) {
- if (err) {
- (*err) += "File not found : " + filename + "\n";
+ if (warn) {
+ (*warn) += "File not found : " + filename + "\n";
}
return false;
}
std::vector<unsigned char> buf;
std::string fileReadErr;
- bool fileRead = fs->ReadWholeFile(&buf, &fileReadErr, filepath,
- fs->user_data);
+ bool fileRead =
+ fs->ReadWholeFile(&buf, &fileReadErr, filepath, fs->user_data);
if (!fileRead) {
if (err) {
(*err) += "File read error : " + filepath + " : " + fileReadErr + "\n";
@@ -1316,9 +1300,11 @@
}
#ifndef TINYGLTF_NO_STB_IMAGE
-bool LoadImageData(Image *image, std::string *err, int req_width,
- int req_height, const unsigned char *bytes, int size,
- void *) {
+bool LoadImageData(Image *image, std::string *err, std::string *warn,
+ int req_width, int req_height, const unsigned char *bytes,
+ int size, void *) {
+ (void)warn;
+
int w, h, comp;
// if image cannot be decoded, ignore parsing and keep it by its path
// don't break in this case
@@ -1328,6 +1314,7 @@
// mandatory (to support other formats)
unsigned char *data = stbi_load_from_memory(bytes, size, &w, &h, &comp, 0);
if (!data) {
+ // NOTE: you can use `warn` instead of `err`
if (err) {
(*err) += "Unknown image format.\n";
}
@@ -1412,11 +1399,11 @@
image->height, image->component, &image->image[0]);
header = "data:image/bmp;base64,";
} else if (!embedImages) {
- // Error: can't output requested format to file
- return false;
+ // Error: can't output requested format to file
+ return false;
}
- if(embedImages) {
+ if (embedImages) {
// Embed base64-encoded image into URI
if (data.size()) {
image->uri =
@@ -1428,12 +1415,12 @@
} else {
// Write image to disc
FsCallbacks *fs = reinterpret_cast<FsCallbacks *>(fsPtr);
- if (fs != nullptr && fs->WriteWholeFile == nullptr)
- {
+ if (fs != nullptr && fs->WriteWholeFile == nullptr) {
const std::string imagefilepath = JoinPath(*basepath, *filename);
std::string writeError;
- if(!fs->WriteWholeFile(&writeError, imagefilepath, data, fs->user_data)) {
- // Could not write image file to disc; Throw error ?
+ if (!fs->WriteWholeFile(&writeError, imagefilepath, data,
+ fs->user_data)) {
+ // Could not write image file to disc; Throw error ?
}
} else {
// Throw error?
@@ -1445,10 +1432,7 @@
}
#endif
-void TinyGLTF::SetFsCallbacks(FsCallbacks callbacks)
-{
- fs = callbacks;
-}
+void TinyGLTF::SetFsCallbacks(FsCallbacks callbacks) { fs = callbacks; }
#ifndef TINYGLTF_NO_FS
// Default implementations of filesystem functions
@@ -1523,7 +1507,6 @@
bool ReadWholeFile(std::vector<unsigned char> *out, std::string *err,
const std::string &filepath, void *) {
-
std::ifstream f(filepath.c_str(), std::ifstream::binary);
if (!f) {
if (err) {
@@ -1538,7 +1521,8 @@
if (int(sz) < 0) {
if (err) {
- (*err) += "Invalid file size : " + filepath + " (does the path point to a directory?)";
+ (*err) += "Invalid file size : " + filepath +
+ " (does the path point to a directory?)";
}
return false;
} else if (sz == 0) {
@@ -1556,11 +1540,8 @@
return true;
}
-bool WriteWholeFile(std::string *err,
- const std::string &filepath,
- const std::vector<unsigned char> &contents,
- void *) {
-
+bool WriteWholeFile(std::string *err, const std::string &filepath,
+ const std::vector<unsigned char> &contents, void *) {
std::ofstream f(filepath.c_str(), std::ofstream::binary);
if (!f) {
if (err) {
@@ -1582,7 +1563,7 @@
return true;
}
-#endif // TINYGLTF_NO_FS
+#endif // TINYGLTF_NO_FS
static std::string MimeToExt(const std::string &mimeType) {
if (mimeType == "image/jpeg") {
@@ -2099,9 +2080,9 @@
return true;
}
-static bool ParseImage(Image *image, std::string *err, const json &o,
- const std::string &basedir,
- FsCallbacks* fs,
+static bool ParseImage(Image *image, std::string *err, std::string *warn,
+ const json &o, const std::string &basedir,
+ FsCallbacks *fs,
LoadImageDataFunction *LoadImageData = nullptr,
void *load_image_user_data = nullptr) {
// A glTF image must either reference a bufferView or an image uri
@@ -2185,17 +2166,17 @@
#ifdef TINYGLTF_NO_EXTERNAL_IMAGE
return true;
#endif
- if (!LoadExternalFile(&img, err, uri, basedir, 0, false, fs)) {
- if (err) {
- (*err) += "Failed to load external 'uri' for image parameter\n";
+ if (!LoadExternalFile(&img, err, warn, uri, basedir, 0, false, fs)) {
+ if (warn) {
+ (*warn) += "Failed to load external 'uri' for image parameter\n";
}
// If the image cannot be loaded, keep uri as image->uri.
return true;
}
if (img.empty()) {
- if (err) {
- (*err) += "Image is empty.\n";
+ if (warn) {
+ (*warn) += "Image is empty.\n";
}
return false;
}
@@ -2207,7 +2188,7 @@
}
return false;
}
- return (*LoadImageData)(image, err, 0, 0, &img.at(0),
+ return (*LoadImageData)(image, err, warn, 0, 0, &img.at(0),
static_cast<int>(img.size()), load_image_user_data);
}
@@ -2232,8 +2213,8 @@
}
static bool ParseBuffer(Buffer *buffer, std::string *err, const json &o,
- FsCallbacks* fs,
- const std::string &basedir, bool is_binary = false,
+ FsCallbacks *fs, const std::string &basedir,
+ bool is_binary = false,
const unsigned char *bin_data = nullptr,
size_t bin_size = 0) {
double byteLength;
@@ -2264,20 +2245,23 @@
size_t bytes = static_cast<size_t>(byteLength);
if (is_binary) {
- // Still binary glTF accepts external dataURI.
+ // Still binary glTF accepts external dataURI.
if (!buffer->uri.empty()) {
// First try embedded data URI.
if (IsDataURI(buffer->uri)) {
std::string mime_type;
- if (!DecodeDataURI(&buffer->data, mime_type, buffer->uri, bytes, true)) {
- if (err) {
- (*err) += "Failed to decode 'uri' : " + buffer->uri + " in Buffer\n";
- }
- return false;
+ if (!DecodeDataURI(&buffer->data, mime_type, buffer->uri, bytes,
+ true)) {
+ if (err) {
+ (*err) +=
+ "Failed to decode 'uri' : " + buffer->uri + " in Buffer\n";
+ }
+ return false;
}
- } else {
+ } else {
// External .bin file.
- LoadExternalFile(&buffer->data, err, buffer->uri, basedir, bytes, true, fs);
+ LoadExternalFile(&buffer->data, err, /* warn */ nullptr, buffer->uri,
+ basedir, bytes, true, fs);
}
} else {
// load data from (embedded) binary data
@@ -2316,8 +2300,8 @@
}
} else {
// Assume external .bin file.
- if (!LoadExternalFile(&buffer->data, err, buffer->uri, basedir, bytes,
- true, fs)) {
+ if (!LoadExternalFile(&buffer->data, err, /* warn */ nullptr, buffer->uri,
+ basedir, bytes, true, fs)) {
return false;
}
}
@@ -2944,8 +2928,9 @@
return true;
}
-bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str,
- unsigned int length, const std::string &base_dir,
+bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
+ const char *str, unsigned int length,
+ const std::string &base_dir,
unsigned int check_sections) {
if (length < 4) {
if (err) {
@@ -3111,9 +3096,8 @@
return false;
}
Buffer buffer;
- if (!ParseBuffer(&buffer, err, it->get<json>(),
- &fs, base_dir, is_binary_,
- bin_data_, bin_size_)) {
+ if (!ParseBuffer(&buffer, err, it->get<json>(), &fs, base_dir,
+ is_binary_, bin_data_, bin_size_)) {
return false;
}
@@ -3314,9 +3298,8 @@
return false;
}
Image image;
- if (!ParseImage(&image, err, it.value(),
- base_dir, &fs, &this->LoadImageData,
- load_image_user_data_)) {
+ if (!ParseImage(&image, err, warn, it.value(), base_dir, &fs,
+ &this->LoadImageData, load_image_user_data_)) {
return false;
}
@@ -3342,7 +3325,7 @@
}
return false;
}
- bool ret = LoadImageData(&image, err, image.width, image.height,
+ bool ret = LoadImageData(&image, err, warn, image.width, image.height,
&buffer.data[bufferView.byteOffset],
static_cast<int>(bufferView.byteLength),
load_image_user_data_);
@@ -3529,25 +3512,27 @@
}
bool TinyGLTF::LoadASCIIFromString(Model *model, std::string *err,
- const char *str, unsigned int length,
+ std::string *warn, const char *str,
+ unsigned int length,
const std::string &base_dir,
unsigned int check_sections) {
is_binary_ = false;
bin_data_ = nullptr;
bin_size_ = 0;
- return LoadFromString(model, err, str, length, base_dir, check_sections);
+ return LoadFromString(model, err, warn, str, length, base_dir,
+ check_sections);
}
bool TinyGLTF::LoadASCIIFromFile(Model *model, std::string *err,
- const std::string &filename,
+ std::string *warn, const std::string &filename,
unsigned int check_sections) {
std::stringstream ss;
if (fs.ReadWholeFile == nullptr) {
// Programmer error, assert() ?
- ss << "Failed to read file: " << filename <<
- ": one or more FS callback not set" << std::endl;
+ ss << "Failed to read file: " << filename
+ << ": one or more FS callback not set" << std::endl;
if (err) {
(*err) = ss.str();
}
@@ -3557,7 +3542,7 @@
std::vector<unsigned char> data;
std::string fileerr;
bool fileread = fs.ReadWholeFile(&data, &fileerr, filename, fs.user_data);
- if(!fileread) {
+ if (!fileread) {
ss << "Failed to read file: " << filename << ": " << fileerr << std::endl;
if (err) {
(*err) = ss.str();
@@ -3575,16 +3560,15 @@
std::string basedir = GetBaseDir(filename);
- bool ret = LoadASCIIFromString(model, err,
- reinterpret_cast<const char *>(&data.at(0)),
- static_cast<unsigned int>(data.size()),
- basedir,
- check_sections);
+ bool ret = LoadASCIIFromString(
+ model, err, warn, reinterpret_cast<const char *>(&data.at(0)),
+ static_cast<unsigned int>(data.size()), basedir, check_sections);
return ret;
}
bool TinyGLTF::LoadBinaryFromMemory(Model *model, std::string *err,
+ std::string *warn,
const unsigned char *bytes,
unsigned int size,
const std::string &base_dir,
@@ -3642,9 +3626,9 @@
bin_size_ =
length - (20 + model_length); // extract header + JSON scene data.
- bool ret =
- LoadFromString(model, err, reinterpret_cast<const char *>(&bytes[20]),
- model_length, base_dir, check_sections);
+ bool ret = LoadFromString(model, err, warn,
+ reinterpret_cast<const char *>(&bytes[20]),
+ model_length, base_dir, check_sections);
if (!ret) {
return ret;
}
@@ -3653,14 +3637,15 @@
}
bool TinyGLTF::LoadBinaryFromFile(Model *model, std::string *err,
+ std::string *warn,
const std::string &filename,
unsigned int check_sections) {
std::stringstream ss;
if (fs.ReadWholeFile == nullptr) {
// Programmer error, assert() ?
- ss << "Failed to read file: " << filename <<
- ": one or more FS callback not set" << std::endl;
+ ss << "Failed to read file: " << filename
+ << ": one or more FS callback not set" << std::endl;
if (err) {
(*err) = ss.str();
}
@@ -3670,7 +3655,7 @@
std::vector<unsigned char> data;
std::string fileerr;
bool fileread = fs.ReadWholeFile(&data, &fileerr, filename, fs.user_data);
- if(!fileread) {
+ if (!fileread) {
ss << "Failed to read file: " << filename << ": " << fileerr << std::endl;
if (err) {
(*err) = ss.str();
@@ -3680,9 +3665,9 @@
std::string basedir = GetBaseDir(filename);
- bool ret = LoadBinaryFromMemory(
- model, err, &data.at(0),
- static_cast<unsigned int>(data.size()), basedir, check_sections);
+ bool ret = LoadBinaryFromMemory(model, err, warn, &data.at(0),
+ static_cast<unsigned int>(data.size()),
+ basedir, check_sections);
return ret;
}