Unlike most other options, where a plugin can support 3D but not 2D or
compressed but not uncompressed data, the "levels" option is orthogonal
to the rest -- if a format supports multi-level data, it obviously also
supports a case where there is just a single level, and if it supports
multi-level images, then it likely supports them for 1D, 2D and 3D, not
just some.
The bit pattern actually followed this reasoning already, but for some
reason I still went ahead and stamped out all possible combinations.
TODO: finish
TODO: OTOH, the ToData is probably better to not have a single bit
common for all, as it makes it impossible to say that e.g. 3D is just
ToFile and 2D and 1D is ToData as well (e.g. when the 3D slices would
need multiple files). So change that to different bits instead.
And not views, as ImageData contains extra metadata. Currently just the
importer state, but eventually that will be changed to a generic
key/value store for stuff like color correction, EXIF, gamma, etc., and
if the plugin interfaces would consume only views (which don't and won't
have such key/value data), the data would get lost.
A similar approach is being taken with the AbstractSceneConverter.
TODO: implement this to be more than just a TODO
Consistently with changes done to Utility::Path, this enforces proper
error handling on user side. Originally I didn't want to do this and
instead wanted to have a special Array instance devoted for an error
state, but that still would allow the error state be errorneously
treated as a successful but empty array.
It's more useful if the Error class is directly referenced than saying
just "error output" -- so people can grab it, redirect it, etc. Also
drop the useless "does what it is expected to do on success" sentences
that add no value whatsoever.
As the CI only uses Linux to test non-deprecated builds, this was
unfortunately not caught -- there std::string is forward-declared in
<iosfwd>, which is included by Debug.h, which is transitively included
by Pointer. On MSVC however a full <string> has to be included always.
Co-authored-by: EhWhoAmI <zyunlam@gmail.com>
I wanted to avoid including extra stuff with the Manager.hpp split, but
this would make it even worse than having Array and String included
unconditionally. Fortunately it's enough to simply not even have the
declaration.
The multi-level APIs still don't check anything regarding level sizes
and order since for example *.ico has no restrictions at all. But the
rest (like non-zero size) is a restriction for all file formats I'm
aware of.
TgaImageConverter test had to be adapted, I expect a lot of breakages in
plugins tests as well. But user code should be fine I think. Also
reduced the rather excessive dimensions in AbstractImageConverterTest,
since the allocation requirement now made the default Emscripten heap
OOM.
To avoid combinatorial explosion of functions that have to be
implemented on the plugin side, the single-image variants proxy to the
multi-level variants, if available.
THe plugin interface string had to be bumped because otherwise there was
a *really nasty* silent ABI break where instead of doSetFlags() it was
suddenly calling doConvert().
Interestingly enough, there were no docs whatsoever for image and scene
conversion, and neither it was mentioned what all scene data can be
imported. Sigh.
This is already done for the AbstractImporter and the new
AbstractShaderConverter, as there's a common use case of checking just
the filename for input/output path or file type detection and then
delegating to the common implementation working directly on data.
First and foremost I need to expand the interface to support 3D
image conversion. But the interface was not great to begin with, so this
takes the opportunity of an API break and does several things:
* The `export*()` names were rather strange and I don't even remember
why I chose that name (maybe because at first I wanted to have an
"exporter" API as a counterpart to importers?)
* In addition, there was no way to convert a compressed image to a
compressed image (or to an uncompressed image) and adding the two
missing variants would be a lot of combinations. So instead the new
convert() returns an ImageData, which can be both, and thus also
allows the converters to produce compressed or uncompressed output
based on some runtime setting, without having to implement two
(four?) separate functions for that and requiring users to know
beforehand what type of an image will be created.
* The ImageConverterFeature enum was named in a really strange way as
well, with ConvertCompressedImage meaning "convert to a compressed
image" while "ConvertCompressedData" instead meant "convert a
compressed image to a data". Utter chaos. It also all implied 2D and
on the other hand had a redundant `Image` in the name, so I went and
remade the whole thing. As mentioned above, two of the enums now mean
the same thing, and are both replaced with Convert2D.
* Finally, similarly as changes elsewhere, I took this opportunity to
get rid of std::string in the convertToFile() APIs.
There will be Flag::FlipY for images at some point, enabled by default
for compatibility with existing GL code, and so it makes sense to start
discouraging setFlags() as early as possible to avoid people resetting
the default by accident.
Also update the imageconverter, sceneconverter and shaderconverter utils
to use these instead of setFlags().