Fix T51292: Alembic import, show notification when trying to load HDF5

HDF5 Alembic files are not officially supported by Blender. With this
commit, the HDF5 format is detected even when Blender is compiled without
HDF5 support, and the user is given an explanatory error message (rather
than the generic "Could not open Alembic archive for reading".
This commit is contained in:
Sybren A. Stüvel 2017-04-25 14:30:01 +02:00
parent ab4f6f01a6
commit 9dadd5ff93
Notes: blender-bot 2023-02-14 07:02:38 +01:00
Referenced by issue #51318, Non-update of preview when switching from world to lamp panel.
Referenced by issue #51292, Show notification when trying to load HDF5
3 changed files with 50 additions and 5 deletions

View File

@ -28,6 +28,8 @@
# include "utfconv.h"
#endif
#include <fstream>
using Alembic::Abc::Exception;
using Alembic::Abc::ErrorHandler;
using Alembic::Abc::IArchive;
@ -38,8 +40,9 @@ static IArchive open_archive(const std::string &filename,
const std::vector<std::istream *> &input_streams,
bool &is_hdf5)
{
is_hdf5 = false;
try {
is_hdf5 = false;
Alembic::AbcCoreOgawa::ReadArchive archive_reader(input_streams);
return IArchive(archive_reader(filename),
@ -63,6 +66,27 @@ static IArchive open_archive(const std::string &filename,
return IArchive();
}
#else
/* Inspect the file to see whether it's really a HDF5 file. */
char header[4]; /* char(0x89) + "HDF" */
std::ifstream the_file(filename, std::ios::in | std::ios::binary);
if (!the_file) {
std::cerr << "Unable to open " << filename << std::endl;
}
else if (!the_file.read(header, sizeof(header))) {
std::cerr << "Unable to read from " << filename << std::endl;
}
else if (strncmp(header + 1, "HDF", 3)) {
std::cerr << filename << " has an unknown file format, unable to read." << std::endl;
}
else {
is_hdf5 = true;
std::cerr << filename << " is in the obsolete HDF5 format, unable to read." << std::endl;
}
if (the_file.is_open()) {
the_file.close();
}
return IArchive();
#endif
}
@ -83,16 +107,20 @@ ArchiveReader::ArchiveReader(const char *filename)
m_streams.push_back(&m_infile);
bool is_hdf5;
m_archive = open_archive(filename, m_streams, is_hdf5);
m_archive = open_archive(filename, m_streams, m_is_hdf5);
/* We can't open an HDF5 file from a stream, so close it. */
if (is_hdf5) {
if (m_is_hdf5) {
m_infile.close();
m_streams.clear();
}
}
bool ArchiveReader::is_hdf5() const
{
return m_is_hdf5;
}
bool ArchiveReader::valid() const
{
return m_archive.valid();

View File

@ -44,12 +44,21 @@ class ArchiveReader {
Alembic::Abc::IArchive m_archive;
std::ifstream m_infile;
std::vector<std::istream *> m_streams;
bool m_is_hdf5;
public:
explicit ArchiveReader(const char *filename);
bool valid() const;
/**
* Returns true when either Blender is compiled with HDF5 support and
* the archive was succesfully opened (valid() will also return true),
* or when Blender was built without HDF5 support but a HDF5 file was
* detected (valid() will return false).
*/
bool is_hdf5() const;
Alembic::Abc::IObject getTop();
};

View File

@ -595,6 +595,7 @@ static std::pair<bool, AbcObjectReader *> visit_object(
enum {
ABC_NO_ERROR = 0,
ABC_ARCHIVE_FAIL,
ABC_UNSUPPORTED_HDF5,
};
struct ImportJobData {
@ -659,8 +660,12 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa
ArchiveReader *archive = new ArchiveReader(data->filename);
if (!archive->valid()) {
delete archive;
#ifndef WITH_ALEMBIC_HDF5
data->error_code = archive->is_hdf5() ? ABC_UNSUPPORTED_HDF5 : ABC_ARCHIVE_FAIL;
#else
data->error_code = ABC_ARCHIVE_FAIL;
#endif
delete archive;
return;
}
@ -829,6 +834,9 @@ static void import_endjob(void *user_data)
case ABC_ARCHIVE_FAIL:
WM_report(RPT_ERROR, "Could not open Alembic archive for reading! See console for detail.");
break;
case ABC_UNSUPPORTED_HDF5:
WM_report(RPT_ERROR, "Alembic archive in obsolete HDF5 format is not supported.");
break;
}
WM_main_add_notifier(NC_SCENE | ND_FRAME, data->scene);