The original implementation had a few problems:
- If a file callback was set, openFile() was unconditionally calling
right into doOpenData(), making it impossible for the importer to
know the original path for correctly supplying paths to additional
files. Now, if the importer supports Feature::FileCallback,
doOpenFile() is always called. It's also possible for the importer to
save the path and then just delegate to the base doOpenFile()
implementation -- it will handle the file callbacks correctly too.
- If the importer supported neither FileCallback nor OpenData and
callbacks were set, the original doOpenFile() implementation was
called without any warning or anything, doing silently a bad thing.
Now in this case setFileCallbacks() asserts -- programmer has to
check for feature support first.
- It was not possible for the file callback to indicate file opening
failure -- in general, empty files are valid, so a nullptr ArrayView
is also a valid file. Now the callback return an Optional instead.
That one is reportedly using the more stable implementation, so just use
it. The code is then also easier to follow. Also added a matrix
decomposition test case and referencing it from the docs, in case
someone would need it again.
Slow and ugly, is here only for making quick'n'dirty alpha masked
drawing without a need for blending or depth sorting. Oh and also to
support the glTF alpha mask feature. Again, beware: *slow*.
MSVC 2015 and 2017 is clueless when it comes to trying to deduce the
template parameters (C2893: Failed to specialize function template). It
works when calling add<V, R> explicitly, but that makes the API hard to
use and inconsistent between platforms. The only possible workaround is
to make add() take *anything*, casting it to proper TrackView type and
then calling add() with explicit template parameters. This also neatly
resolves the Track/TrackView overload, as the static_cast is either a
no-op or it invokes the conversion operator on Track. The original code
also reportedly makes the Intellisense freezing like hell and adding
this overload fixes the freezes. Three birds with one stone.
The Player class definition is now full of typedefs, with the amount of
comments about why the typedefs are there much bigger than the actual
code. Oh well.
At the moment, with the major use case, which is playing back glTF
animations, one can't use atStrict() because there Extrapolation is
specified to be always Constant. The atStrict() function behaves as
Extrapolate and one would need to patch the imported tracks to add
explicit keyframes at the beginning/end of the duration that emulate the
Constant behavior.