Initially I thought there was no reason for this to fail, but then
realized AnySceneConverter would need it. And also any other plugin
relying on something external that might fail during initialization --
there's no other moment after plugin instantiation where it could
signalize a failure, and deferring that to the first add() call,
whichever would it be, is really not a sane idea.
Wasn't really possible to split this into multiple commits, so here's
the whole thing including delegation from and to the single-mesh APIs.
What's not done here and postponed for later is:
- an ability to feed the whole importer to it, filtering away data that
aren't supported by the converter
- corresponding changes in AbstractImageConverter, where it would now
primarily accept ImageData to future-proof for arbitrary extra
key/value data
They are required to have the same format already, so flags make sense
as well -- what's the point of saving a multi-level cube map with one of
the levels being just a 2D array, anyway?
With the intention that those will eventually contain also things like
YUp / YDown, PremultipliedAlpha and such.
This commit is mostly just busywork, wiring this into [Compressed]Image,
[Compressed]ImageView and Trade::ImageData and ensuring the flags get
correctly propagated during moves and conversions. Unfortunately in case
of Trade::ImageData it meant deprecating the current set of constructor
in order to insert an ImageFlags parameter before the importer state
pointer.
The only non-trivial piece of logic is when a 2D
[Compressed]ImageView gets converted to a 3D one, then the Array bit is
implicitly dropped, as 2D arrays of 1D images are not really a thing.
Instead, it's now possible to add new flags when doing the conversion --
for example to turn a 2D image to a (single-layer) 2D array image.
For consistency with how VertexFormat and other enum helpers are named.
The compressedBlockSize() and compressedBlockDataSize() is also renamed
to compressedPixelFormatBlockSize() and
compressedPixelFormatBlockDataSize().
While backwards compatibility aliases are in place, a breaking change
is that Image classes now look for pixelFormatSize() instead of
pixelSize(). This is used e.g. when passing GL::PixelFormat /
GL::PixelType to the image classes, instead of the generic PixelFormat.
While useful, it's unlikely that any project was defining their own
pixel format enum and pixelSize() for a D3D or Metal renderer or
whatnot, so the breakage should have no practical impact.
Logic mostly the same as with MaterialAttribute::*TextureCoordinates --
attribute not present is treated the same way as if the layer was 0
(since that's what a 2D non-array texture is, a single-slice array), and
conversely if the attribute is 0 it's the same as if it would be not
present at all. Plus it also gets checked in queries for packed
textures, if everything is the same but the layer is different, then
it's not a packed texture.
The rest of the commit is just busywork for convenience APIs.
In particular, returning true only if some coordinate set index is
non-zero -- the main use case is to know whether we need a complex
shader with multiple coordinate attributes or not.
Only PhongMaterialData do that, others not.
Hey, do you also remember the times where people were excited to upgrade
from Clang 3.6 to 3.7, GCC 4.7 to 4.8 or Firefox 1.1 to Firefox 1.5? Not
Clang 12 to 14, GCC 10 to 13 or Chrome 102 to 126.
While branching on a compiler is rather common, checking a particular
compiler version should be needed only rarely. Thus minimize use of such
macros to make them easier to grep for.
I realized those are too annoying when writing a glTF exporter which
contains a lot of switches over enums. And as further shown by the diff,
those were only inflicting additional pain in *all* switch statements,
nothing else, no other added value. And everywhere else the helpers are
the designated way to deal with those, so there's no point in having an
explicit enum value denoting start of a "custom range".
It wasn't even any convenient to have it in the enum, as the extra
effort needed for casting actually made it *exactly* the same length as
if I'd just use a separately-defined constant.
Until now, these were only transitively tested in concrete plugin
implementations, meaning that if the base implementation would have an
error (such as accessing a null optional), it would only get discovered
when building a plugin, worst case a plugin in a completely different
repo.
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.
Again not publicly documented because I don't like the naming and I
don't have the full behavior and interactions figured out yet -- i.e.,
an array of VertexFormats would be printed with Debug::packed as a long
string of characters without any whitespace. Not good, thus this
feature probably needs to be split in two, with this being named
"compact" or something else.
It limits the support for CMake 3.12+, but it's much less verbose and I
don't expect people to use ancient CMake versions with IDEs like Xcode
or VS anyway, so this should be fine.
Except for file callbacks, for these I have another change planned for
zero-copy import and it would be unwise to break stuff twice, providing
two sets of backwards compatibility wrappers. The image / scene
converter plugins went through a similar change earlier already and the
shader converters were made sane since the very beginning. OTOH audio
importers and text stuff are scheduled for merging with Trade or a
larger rework anyway, so I didn't see any point in updating those.
It's mostly a trivial change, except that returned String instances are
now also checked for non-default deleters same as Arrays because yes,
wow such flexibility compared to STL strings. Same was done for
ShaderTools::AbstractConverter already anyway, so nothing unheard-of
either.
The importer plugin interface version is bumped as this likely breaks
ABI in a nasty way that would lead to crashes.
For file opening there's no longer an unatomic pair of exists() +
read(), but since Path::read() now returns an Optional, it means we can
reliably distinguish between empty files and failures.
While at it, also added TODOs for removal of the StringStl.h header
that's needed in various places for compatibility with APIs still using
STL strings.
It's dangerous, as in case of failure it will attempt to print them as
strings. Plus now with latest de-std-string-ification of TestSuite it
causes the compilation to fail due to an ambigupus overload.
This should eventually be catched and disallowed directly by the Tester
class.
With really huge materials it's kinda useless to not know which layer
the error happened in -- and usually it's exactly because the layer
indices were specified wrong.
It was a clever harmless trick. Well, it was way more harmless than it
was clever, but even then it caused UBSan to complain. And that's Not A
Good Thing for various reasons, so let's just comply.
The main bad effect of this change is a *slightly* larger list of
exported symbols but until we actually get rid of the major bloats like
<iostream>, <string> and the like, this is not going to have any
measurable impact.
This mirrors what's done already for implementation-specific vertex
formats, thus:
* Ability to construct the classes without tripping up when trying to
check for type size in various asserts
* Providing a zero-size type-erased access in indices() and
mutableIndices()
* Disallowing typed and convenience access
Also not something the classic GPU vertex pipeline can handle, but
useful for other scenarios. Subsequently a support for array indices
will be added, allowing to directly represent for example OBJ files,
where each attribute has its own index buffer.
This is not something the classic GPU vertex pipeline can handle
(except maybe Vulkan, which can handle zero strides for instanced
attributes?), but useful for other scenarios. This means existing code
needs to be aware of and handle the new corner case.
No functional change, just splitting them to two separate headers and
two separate tests. These will eventually become public SceneTools
APIs... once I figure out better naming.