From 9dadd5ff937f81cc1e5aa9136b8eafb5a5414bb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Tue, 25 Apr 2017 14:30:01 +0200 Subject: 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". --- source/blender/alembic/intern/abc_archive.cc | 36 ++++++++++++++++++++++++--- source/blender/alembic/intern/abc_archive.h | 9 +++++++ source/blender/alembic/intern/alembic_capi.cc | 10 +++++++- 3 files changed, 50 insertions(+), 5 deletions(-) (limited to 'source/blender/alembic') diff --git a/source/blender/alembic/intern/abc_archive.cc b/source/blender/alembic/intern/abc_archive.cc index 5f8fc1a3739..cdbda0ace69 100644 --- a/source/blender/alembic/intern/abc_archive.cc +++ b/source/blender/alembic/intern/abc_archive.cc @@ -28,6 +28,8 @@ # include "utfconv.h" #endif +#include + 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 &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(); diff --git a/source/blender/alembic/intern/abc_archive.h b/source/blender/alembic/intern/abc_archive.h index d412574b736..84309fbc9df 100644 --- a/source/blender/alembic/intern/abc_archive.h +++ b/source/blender/alembic/intern/abc_archive.h @@ -44,12 +44,21 @@ class ArchiveReader { Alembic::Abc::IArchive m_archive; std::ifstream m_infile; std::vector 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(); }; diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index e44f66b7e56..50e7626ad1e 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -595,6 +595,7 @@ static std::pair 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); -- cgit v1.2.3