Browse Source

Put single-statement branch contents on the following line.

next
Vladimír Vondruš 2 months ago
parent
commit
fdfe327f9a
  1. 3
      doc/generated/atlas.cpp
  2. 3
      doc/generated/easings.cpp
  3. 3
      doc/snippets/Animation.cpp
  4. 3
      doc/snippets/DebugTools.cpp
  5. 6
      doc/snippets/Magnum.cpp
  6. 3
      doc/snippets/Math.cpp
  7. 3
      doc/snippets/SceneTools.cpp
  8. 6
      doc/snippets/ShaderTools.cpp
  9. 6
      doc/snippets/Text.cpp
  10. 9
      doc/snippets/Trade.cpp
  11. 3
      doc/snippets/Vk.cpp
  12. 3
      doc/snippets/plugins.cpp
  13. 9
      src/Magnum/AbstractResourceLoader.h
  14. 44
      src/Magnum/Animation/Easing.h
  15. 21
      src/Magnum/Animation/Interpolation.h
  16. 6
      src/Magnum/Animation/Player.h
  17. 27
      src/Magnum/Animation/Player.hpp
  18. 3
      src/Magnum/Animation/Test/PlayerTest.cpp
  19. 6
      src/Magnum/Array.h
  20. 5
      src/Magnum/Audio/Buffer.h
  21. 18
      src/Magnum/Audio/Context.cpp
  22. 6
      src/Magnum/Audio/Listener.cpp
  23. 3
      src/Magnum/Audio/Source.cpp
  24. 5
      src/Magnum/Audio/Source.h
  25. 3
      src/Magnum/Audio/Test/GlobalStateAcrossLibrariesLibrary.cpp
  26. 3
      src/Magnum/Audio/al-info.cpp
  27. 3
      src/Magnum/DebugTools/BufferData.h
  28. 18
      src/Magnum/DebugTools/CompareImage.cpp
  29. 6
      src/Magnum/DebugTools/CompareMaterial.cpp
  30. 6
      src/Magnum/DebugTools/ForceRenderer.cpp
  31. 39
      src/Magnum/DebugTools/FrameProfiler.cpp
  32. 6
      src/Magnum/DebugTools/ObjectRenderer.cpp
  33. 15
      src/Magnum/DebugTools/Profiler.cpp
  34. 3
      src/Magnum/DebugTools/Test/FrameProfilerGLTest.cpp
  35. 21
      src/Magnum/GL/AbstractShaderProgram.cpp
  36. 18
      src/Magnum/GL/AbstractTexture.cpp
  37. 6
      src/Magnum/GL/Attribute.cpp
  38. 12
      src/Magnum/GL/Buffer.cpp
  39. 18
      src/Magnum/GL/Context.cpp
  40. 5
      src/Magnum/GL/DebugOutput.h
  41. 4
      src/Magnum/GL/DefaultFramebuffer.cpp
  42. 7
      src/Magnum/GL/Framebuffer.cpp
  43. 3
      src/Magnum/GL/Implementation/BufferState.cpp
  44. 6
      src/Magnum/GL/Implementation/MeshState.cpp
  45. 3
      src/Magnum/GL/Implementation/State.cpp
  46. 21
      src/Magnum/GL/Mesh.cpp
  47. 3
      src/Magnum/GL/MeshView.cpp
  48. 3
      src/Magnum/GL/PrimitiveQuery.cpp
  49. 3
      src/Magnum/GL/Renderbuffer.cpp
  50. 12
      src/Magnum/GL/Shader.cpp
  51. 18
      src/Magnum/GL/Test/CubeMapTextureGLTest.cpp
  52. 3
      src/Magnum/GL/Test/MeshGLTest.cpp
  53. 3
      src/Magnum/GL/TransformFeedback.cpp
  54. 3
      src/Magnum/Image.cpp
  55. 6
      src/Magnum/ImageView.cpp
  56. 3
      src/Magnum/ImageView.h
  57. 6
      src/Magnum/MaterialTools/Filter.cpp
  58. 6
      src/Magnum/MaterialTools/PhongToPbrMetallicRoughness.cpp
  59. 3
      src/Magnum/Math/Algorithms/KahanSum.h
  60. 6
      src/Magnum/Math/Algorithms/Svd.h
  61. 3
      src/Magnum/Math/Bezier.h
  62. 9
      src/Magnum/Math/BitVector.h
  63. 3
      src/Magnum/Math/Color.h
  64. 3
      src/Magnum/Math/Complex.h
  65. 9
      src/Magnum/Math/ConfigurationValue.h
  66. 9
      src/Magnum/Math/Frustum.h
  67. 6
      src/Magnum/Math/Functions.cpp
  68. 21
      src/Magnum/Math/Functions.h
  69. 31
      src/Magnum/Math/FunctionsBatch.h
  70. 6
      src/Magnum/Math/Intersection.h
  71. 3
      src/Magnum/Math/Matrix.h
  72. 6
      src/Magnum/Math/Quaternion.h
  73. 9
      src/Magnum/Math/Range.h
  74. 9
      src/Magnum/Math/RectangularMatrix.h
  75. 3
      src/Magnum/Math/Test/IntersectionBenchmark.cpp
  76. 6
      src/Magnum/Math/TypeTraits.h
  77. 10
      src/Magnum/Math/Vector.h
  78. 6
      src/Magnum/Mesh.cpp
  79. 3
      src/Magnum/MeshTools/BoundingVolume.cpp
  80. 9
      src/Magnum/MeshTools/Compile.cpp
  81. 9
      src/Magnum/MeshTools/Concatenate.cpp
  82. 3
      src/Magnum/MeshTools/Duplicate.cpp
  83. 15
      src/Magnum/MeshTools/GenerateNormals.cpp
  84. 15
      src/Magnum/MeshTools/Interleave.cpp
  85. 12
      src/Magnum/MeshTools/RemoveDuplicates.cpp
  86. 3
      src/Magnum/MeshTools/Test/CompileGLTest.cpp
  87. 6
      src/Magnum/MeshTools/Test/InterleaveTest.cpp
  88. 12
      src/Magnum/MeshTools/Tipsify.cpp
  89. 24
      src/Magnum/MeshTools/Transform.h
  90. 6
      src/Magnum/PixelFormat.cpp
  91. 15
      src/Magnum/Platform/AbstractXApplication.cpp
  92. 3
      src/Magnum/Platform/AndroidApplication.cpp
  93. 27
      src/Magnum/Platform/EmscriptenApplication.cpp
  94. 45
      src/Magnum/Platform/GlfwApplication.cpp
  95. 48
      src/Magnum/Platform/ScreenedApplication.hpp
  96. 54
      src/Magnum/Platform/Sdl2Application.cpp
  97. 3
      src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp
  98. 3
      src/Magnum/Platform/Test/GlfwApplicationTest.cpp
  99. 6
      src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp
  100. 9
      src/Magnum/Platform/WindowlessCglApplication.cpp
  101. Some files were not shown because too many files have changed in this diff Show More

3
doc/generated/atlas.cpp

@ -88,7 +88,8 @@ int main() {
data[i].size = Vector2i{1 << currentSize}; data[i].size = Vector2i{1 << currentSize};
if(i) size.x() += padding; if(i)
size.x() += padding;
size.x() += data[i].size.x(); size.x() += data[i].size.x();
size.y() = Math::max(size.y(), data[i].size.y()); size.y() = Math::max(size.y(), data[i].size.y());
} }

3
doc/generated/easings.cpp

@ -160,7 +160,8 @@ void generate(Containers::StringView file, Float(*function)(Float), std::initial
)"); )");
}; };
for(auto fn: related) print(0x747474_srgbf, 1.0f, fn); for(auto fn: related)
print(0x747474_srgbf, 1.0f, fn);
/* Bezier representation, if any */ /* Bezier representation, if any */
if(!bezier[3].isZero()) { if(!bezier[3].isZero()) {

3
doc/snippets/Animation.cpp

@ -275,7 +275,8 @@ player.addRawCallback(track,
std::size_t& hint, void* destination, void(*callback)(), void* userData) { std::size_t& hint, void* destination, void(*callback)(), void* userData) {
Int value = static_cast<const Animation::TrackView<const Float, const Int>&>(track) Int value = static_cast<const Animation::TrackView<const Float, const Int>&>(track)
.atStrict(key, hint); .atStrict(key, hint);
if(value == *static_cast<Int*>(destination)) return; if(value == *static_cast<Int*>(destination))
return;
*static_cast<Int*>(destination) = value; *static_cast<Int*>(destination) = value;
reinterpret_cast<void(*)(std::vector<Int>&, Int)>(callback) reinterpret_cast<void(*)(std::vector<Int>&, Int)>(callback)
(*static_cast<std::vector<Int>*>(userData), value); (*static_cast<std::vector<Int>*>(userData), value);

3
doc/snippets/DebugTools.cpp

@ -136,7 +136,8 @@ void MyApp::drawEventAgain() {
_profiler.printStatistics(10); _profiler.printStatistics(10);
swapBuffers(); swapBuffers();
if(_profiler.isEnabled()) redraw(); if(_profiler.isEnabled())
redraw();
} }
/* [FrameProfiler-usage-console] */ /* [FrameProfiler-usage-console] */

6
doc/snippets/Magnum.cpp

@ -123,9 +123,9 @@ std::nullptr_t data = nullptr;
Image2D image{PixelFormat::RGB8Unorm, {128, 128}, data}; Image2D image{PixelFormat::RGB8Unorm, {128, 128}, data};
Containers::StridedArrayView2D<Color3ub> pixels = image.pixels<Color3ub>(); Containers::StridedArrayView2D<Color3ub> pixels = image.pixels<Color3ub>();
for(auto row: pixels.sliceSize({48, 48}, {32, 32})) { for(auto row: pixels.sliceSize({48, 48}, {32, 32}))
for(Color3ub& pixel: row) pixel *= 1.1f; for(Color3ub& pixel: row)
} pixel *= 1.1f;
/* [Image-pixels] */ /* [Image-pixels] */
} }

3
doc/snippets/Math.cpp

@ -1106,7 +1106,8 @@ Math::Dual<Byte> integral{floatingPoint}; // {1, 2}
Frustum frustum; Frustum frustum;
/* [Frustum-range] */ /* [Frustum-range] */
for(Vector4 plane: frustum) for(Vector4 plane: frustum)
if(Math::Distance::pointPlaneScaled(point, plane) < 0.0f) return false; if(Math::Distance::pointPlaneScaled(point, plane) < 0.0f)
return false;
return true; return true;
/* [Frustum-range] */ /* [Frustum-range] */
}({}); }({});

3
doc/snippets/SceneTools.cpp

@ -118,7 +118,8 @@ Containers::BitArray objectsToKeep{ValueInit, std::size_t(scene.mappingBound())}
/* Look for the object in the list */ /* Look for the object in the list */
for(const Containers::Pair<UnsignedInt, UnsignedInt>& i: childrenRanges) { for(const Containers::Pair<UnsignedInt, UnsignedInt>& i: childrenRanges) {
if(i.first() != objectToLookFor) continue; if(i.first() != objectToLookFor)
continue;
/* Right after the object appearing in the list is all its (nested) /* Right after the object appearing in the list is all its (nested)
children, mark them in the bit array */ children, mark them in the bit array */

6
doc/snippets/ShaderTools.cpp

@ -146,7 +146,8 @@ converter->setInputFileCallback([](const std::string& filename,
/* Discard the loaded file, if not needed anymore */ /* Discard the loaded file, if not needed anymore */
if(policy == InputFileCallbackPolicy::Close) { if(policy == InputFileCallbackPolicy::Close) {
if(found != data.files.end()) data.files.erase(found); if(found != data.files.end())
data.files.erase(found);
return {}; return {};
} }
@ -156,7 +157,8 @@ converter->setInputFileCallback([](const std::string& filename,
if(found == data.files.end()) found = data.files.emplace( if(found == data.files.end()) found = data.files.emplace(
filename, extract("shaders.zip", filename)).first; filename, extract("shaders.zip", filename)).first;
if(!found->second) return {}; if(!found->second)
return {};
return Containers::ArrayView<const char>{*found->second}; return Containers::ArrayView<const char>{*found->second};
}, data); }, data);

6
doc/snippets/Text.cpp

@ -169,7 +169,8 @@ font->setFileCallback([](const std::string& filename,
/* Discard the memory mapping, if not needed anymore */ /* Discard the memory mapping, if not needed anymore */
if(policy == InputFileCallbackPolicy::Close) { if(policy == InputFileCallbackPolicy::Close) {
if(found != data.files.end()) data.files.erase(found); if(found != data.files.end())
data.files.erase(found);
return {}; return {};
} }
@ -178,7 +179,8 @@ font->setFileCallback([](const std::string& filename,
if(found == data.files.end()) found = data.files.emplace( if(found == data.files.end()) found = data.files.emplace(
filename, Utility::Path::mapRead(filename)).first; filename, Utility::Path::mapRead(filename)).first;
if(!found->second) return {}; if(!found->second)
return {};
return Containers::arrayView(*found->second); return Containers::arrayView(*found->second);
}, data); }, data);

9
doc/snippets/Trade.cpp

@ -187,7 +187,8 @@ if(!importer || !importer->openFile("image.png"))
Fatal{} << "Can't open image.png with AnyImageImporter"; Fatal{} << "Can't open image.png with AnyImageImporter";
Containers::Optional<Trade::ImageData2D> image = importer->image2D(0); Containers::Optional<Trade::ImageData2D> image = importer->image2D(0);
if(!image) Fatal{} << "Importing the image failed"; if(!image)
Fatal{} << "Importing the image failed";
// use the image ... // use the image ...
/* [AbstractImporter-usage] */ /* [AbstractImporter-usage] */
@ -230,7 +231,8 @@ importer->setFileCallback([](const std::string& filename,
/* Discard the memory mapping, if not needed anymore */ /* Discard the memory mapping, if not needed anymore */
if(policy == InputFileCallbackPolicy::Close) { if(policy == InputFileCallbackPolicy::Close) {
if(found != data.files.end()) data.files.erase(found); if(found != data.files.end())
data.files.erase(found);
return {}; return {};
} }
@ -239,7 +241,8 @@ importer->setFileCallback([](const std::string& filename,
if(found == data.files.end()) found = data.files.emplace( if(found == data.files.end()) found = data.files.emplace(
filename, Utility::Path::mapRead(filename)).first; filename, Utility::Path::mapRead(filename)).first;
if(!found->second) return {}; if(!found->second)
return {};
return Containers::arrayView(*found->second); return Containers::arrayView(*found->second);
}, data); }, data);

3
doc/snippets/Vk.cpp

@ -354,7 +354,8 @@ Vk::DescriptorPool pool{NoCreate}, overflowPool{NoCreate};
Containers::Optional<Vk::DescriptorSet> set = pool.tryAllocate(layout); Containers::Optional<Vk::DescriptorSet> set = pool.tryAllocate(layout);
/* Oops, the pool is full (or fragmented). Hope the plan B doesn't fail too. */ /* Oops, the pool is full (or fragmented). Hope the plan B doesn't fail too. */
if(!set) set = overflowPool.allocate(layout); if(!set)
set = overflowPool.allocate(layout);
/* [DescriptorSet-allocation-try] */ /* [DescriptorSet-allocation-try] */
} }

3
doc/snippets/plugins.cpp

@ -56,7 +56,8 @@ void mainPlugins() {
PluginManager::Manager<Trade::AbstractImporter> manager; PluginManager::Manager<Trade::AbstractImporter> manager;
Containers::Pointer<Trade::AbstractImporter> importer = Containers::Pointer<Trade::AbstractImporter> importer =
manager.loadAndInstantiate("TgaImporter"); manager.loadAndInstantiate("TgaImporter");
if(!importer) Fatal{} << "Cannot load the TgaImporter plugin"; if(!importer)
Fatal{} << "Cannot load the TgaImporter plugin";
// Use the plugin... // Use the plugin...

9
src/Magnum/AbstractResourceLoader.h

@ -264,7 +264,8 @@ template<class T> class CORRADE_DEPRECATED("the ResourceManager class is obsolet
CORRADE_IGNORE_DEPRECATED_PUSH CORRADE_IGNORE_DEPRECATED_PUSH
template<class T> AbstractResourceLoader<T>::~AbstractResourceLoader() { template<class T> AbstractResourceLoader<T>::~AbstractResourceLoader() {
if(manager) manager->_loader = nullptr; if(manager)
manager->_loader = nullptr;
} }
template<class T> std::string AbstractResourceLoader<T>::doName(ResourceKey) const { return {}; } template<class T> std::string AbstractResourceLoader<T>::doName(ResourceKey) const { return {}; }
@ -277,8 +278,10 @@ template<class T> void AbstractResourceLoader<T>::load(ResourceKey key) {
} }
template<class T> void AbstractResourceLoader<T>::set(ResourceKey key, T* data, ResourceDataState state, ResourcePolicy policy) { template<class T> void AbstractResourceLoader<T>::set(ResourceKey key, T* data, ResourceDataState state, ResourcePolicy policy) {
if(data) ++_loadedCount; if(data)
if(!data && state == ResourceDataState::NotFound) ++_notFoundCount; ++_loadedCount;
if(!data && state == ResourceDataState::NotFound)
++_notFoundCount;
manager->set(key, data, state, policy); manager->set(key, data, state, policy);
} }
CORRADE_IGNORE_DEPRECATED_POP CORRADE_IGNORE_DEPRECATED_POP

44
src/Magnum/Animation/Easing.h

@ -366,8 +366,10 @@ template<class T> struct BasicEasing {
static T smoothstep(T t) { static T smoothstep(T t) {
/* Deliberately *not* using Math::clamp() because that would drag in /* Deliberately *not* using Math::clamp() because that would drag in
unneeded vector headers */ unneeded vector headers */
if(t <= T(0.0)) return T(0.0); if(t <= T(0.0))
if(t >= T(1.0)) return T(1.0); return T(0.0);
if(t >= T(1.0))
return T(1.0);
return (T(3.0) - T(2.0)*t)*t*t; return (T(3.0) - T(2.0)*t)*t*t;
} }
@ -391,8 +393,10 @@ template<class T> struct BasicEasing {
static T smootherstep(T t) { static T smootherstep(T t) {
/* Deliberately *not* using Math::clamp() because that would drag in /* Deliberately *not* using Math::clamp() because that would drag in
unneeded vector headers */ unneeded vector headers */
if(t <= T(0.0)) return T(0.0); if(t <= T(0.0))
if(t >= T(1.0)) return T(1.0); return T(0.0);
if(t >= T(1.0))
return T(1.0);
return t*t*t*(t*(t*T(6.0) - T(15.0)) + T(10.0)); return t*t*t*(t*(t*T(6.0) - T(15.0)) + T(10.0));
} }
@ -451,8 +455,8 @@ template<class T> struct BasicEasing {
* @see @ref cubicInOut(), @ref quarticInOut(), @ref quinticInOut() * @see @ref cubicInOut(), @ref quarticInOut(), @ref quinticInOut()
*/ */
static T quadraticInOut(T t) { static T quadraticInOut(T t) {
if(t < T(0.5)) return T(2.0)*t*t; if(t < T(0.5))
return T(2.0)*t*t;
const T inv = T(1.0) - t; const T inv = T(1.0) - t;
return T(1.0) - T(2.0)*inv*inv; return T(1.0) - T(2.0)*inv*inv;
} }
@ -515,8 +519,8 @@ template<class T> struct BasicEasing {
* @see @ref quadraticInOut(), @ref quarticInOut(), @ref quinticInOut() * @see @ref quadraticInOut(), @ref quarticInOut(), @ref quinticInOut()
*/ */
static T cubicInOut(T t) { static T cubicInOut(T t) {
if(t < T(0.5)) return T(4.0)*t*t*t; if(t < T(0.5))
return T(4.0)*t*t*t;
const T inv = T(1.0) - t; const T inv = T(1.0) - t;
return T(1.0) - T(4.0)*inv*inv*inv; return T(1.0) - T(4.0)*inv*inv*inv;
} }
@ -748,7 +752,8 @@ template<class T> struct BasicEasing {
* @see @ref sineInOut() * @see @ref sineInOut()
*/ */
static T circularInOut(T t) { static T circularInOut(T t) {
if(t < T(0.5)) return T(0.5)*(T(1.0) - std::sqrt(T(1.0) - T(4.0)*t*t)); if(t < T(0.5))
return T(0.5)*(T(1.0) - std::sqrt(T(1.0) - T(4.0)*t*t));
return T(0.5)*(T(1.0) + std::sqrt(T(-4.0)*t*t + T(8.0)*t - T(3.0))); return T(0.5)*(T(1.0) + std::sqrt(T(-4.0)*t*t + T(8.0)*t - T(3.0)));
} }
@ -818,9 +823,12 @@ template<class T> struct BasicEasing {
* @f] * @f]
*/ */
static T exponentialInOut(T t) { static T exponentialInOut(T t) {
if(t <= T(0.0)) return T(0.0); if(t <= T(0.0))
if(t < T(0.5)) return T(0.5)*std::pow(T(2.0), T(20.0)*t - T(10.0)); return T(0.0);
if(t < T(1.0)) return T(1.0) - T(0.5)*std::pow(T(2.0), T(10.0) -T(20.0)*t); if(t < T(0.5))
return T(0.5)*std::pow(T(2.0), T(20.0)*t - T(10.0));
if(t < T(1.0))
return T(1.0) - T(0.5)*std::pow(T(2.0), T(10.0) -T(20.0)*t);
return T(1.0); return T(1.0);
} }
@ -943,9 +951,12 @@ template<class T> struct BasicEasing {
* @htmlinclude easings-bounceout.svg * @htmlinclude easings-bounceout.svg
*/ */
static T bounceOut(T t) { static T bounceOut(T t) {
if(t < T(4.0)/T(11.0)) return (T(121.0)*t*t)/T(16.0); if(t < T(4.0)/T(11.0))
if(t < T(8.0)/T(11.0)) return T(363.0)/T(40.0)*t*t - T(99.0)/T(10.0)*t + T(17.0)/T(5.0); return (T(121.0)*t*t)/T(16.0);
if(t < T(9.0)/T(10.0)) return T(4356.0)/T(361.0)*t*t - T(35442.0)/T(1805.0)*t + T(16061.0)/T(1805.0); if(t < T(8.0)/T(11.0))
return T(363.0)/T(40.0)*t*t - T(99.0)/T(10.0)*t + T(17.0)/T(5.0);
if(t < T(9.0)/T(10.0))
return T(4356.0)/T(361.0)*t*t - T(35442.0)/T(1805.0)*t + T(16061.0)/T(1805.0);
return T(54.0)/T(5.0)*t*t - T(513.0)/T(25.0)*t + T(268.0)/T(25.0); return T(54.0)/T(5.0)*t*t - T(513.0)/T(25.0)*t + T(268.0)/T(25.0);
} }
@ -957,7 +968,8 @@ template<class T> struct BasicEasing {
* @htmlinclude easings-bounceinout.svg * @htmlinclude easings-bounceinout.svg
*/ */
static T bounceInOut(T t) { static T bounceInOut(T t) {
if(t < T(0.5)) return T(0.5)*bounceIn(T(2.0)*t); if(t < T(0.5))
return T(0.5)*bounceIn(T(2.0)*t);
return T(0.5)*bounceOut(T(2.0)*t - T(1.0)) + T(0.5); return T(0.5)*bounceOut(T(2.0)*t - T(1.0)) + T(0.5);
} }
}; };

21
src/Magnum/Animation/Interpolation.h

@ -420,7 +420,8 @@ template<class K, class V, class R> R interpolate(const Containers::StridedArray
CORRADE_ASSERT(keys.size() == values.size(), "Animation::interpolate(): keys and values don't have the same size", {}); CORRADE_ASSERT(keys.size() == values.size(), "Animation::interpolate(): keys and values don't have the same size", {});
/* No data, return default-constructed value */ /* No data, return default-constructed value */
if(!keys.size()) return {}; if(!keys.size())
return {};
/* Only one frame, return it verbatim (or default-constructed, if desired) */ /* Only one frame, return it verbatim (or default-constructed, if desired) */
if(keys.size() == 1) { if(keys.size() == 1) {
@ -432,7 +433,8 @@ template<class K, class V, class R> R interpolate(const Containers::StridedArray
} }
/* Rewind from the beginning if hint is too late */ /* Rewind from the beginning if hint is too late */
if(hint >= keys.size() || frame < keys[hint]) hint = 0; if(hint >= keys.size() || frame < keys[hint])
hint = 0;
/* Go through the keys until we find a pair that is around given time */ /* Go through the keys until we find a pair that is around given time */
while(hint + 2 < keys.size() && frame >= keys[hint + 1]) while(hint + 2 < keys.size() && frame >= keys[hint + 1])
@ -441,11 +443,15 @@ template<class K, class V, class R> R interpolate(const Containers::StridedArray
/* Special extrapolation outside of range. Usual extrapolation is handled /* Special extrapolation outside of range. Usual extrapolation is handled
below. */ below. */
if(frame < keys[hint]) { if(frame < keys[hint]) {
if(before == Extrapolation::DefaultConstructed) return {}; if(before == Extrapolation::DefaultConstructed)
if(before == Extrapolation::Constant) frame = keys[hint]; return {};
if(before == Extrapolation::Constant)
frame = keys[hint];
} else if(frame >= keys[hint + 1]) { } else if(frame >= keys[hint + 1]) {
if(after == Extrapolation::DefaultConstructed) return {}; if(after == Extrapolation::DefaultConstructed)
if(after == Extrapolation::Constant) frame = keys[hint + 1]; return {};
if(after == Extrapolation::Constant)
frame = keys[hint + 1];
} }
return interpolator(values[hint], values[hint + 1], return interpolator(values[hint], values[hint + 1],
@ -457,7 +463,8 @@ template<class K, class V, class R> R interpolateStrict(const Containers::Stride
CORRADE_ASSERT(keys.size() == values.size(), "Animation::interpolateStrict(): keys and values don't have the same size", {}); CORRADE_ASSERT(keys.size() == values.size(), "Animation::interpolateStrict(): keys and values don't have the same size", {});
/* Rewind from the beginning if hint is too late */ /* Rewind from the beginning if hint is too late */
if(hint >= keys.size() || frame < keys[hint]) hint = 0; if(hint >= keys.size() || frame < keys[hint])
hint = 0;
/* Go through the keys until we find a pair that is around given time */ /* Go through the keys until we find a pair that is around given time */
while(hint + 2 < keys.size() && frame >= keys[hint + 1]) while(hint + 2 < keys.size() && frame >= keys[hint + 1])

6
src/Magnum/Animation/Player.h

@ -850,7 +850,8 @@ template<class T, class K> template<class V, class R, class Callback> Player<T,
[](const TrackViewStorage<const K>& track, K key, std::size_t& hint, void* destination, void(*callback)(), void* userData) { [](const TrackViewStorage<const K>& track, K key, std::size_t& hint, void* destination, void(*callback)(), void* userData) {
/** @todo try to use atStrict() if possible */ /** @todo try to use atStrict() if possible */
R result = static_cast<const TrackView<const K, const V, R>&>(track).at(key, hint); R result = static_cast<const TrackView<const K, const V, R>&>(track).at(key, hint);
if(result == *static_cast<R*>(destination)) return; if(result == *static_cast<R*>(destination))
return;
reinterpret_cast<void(*)(K, const R&, void*)>(callback)(key, result, userData); reinterpret_cast<void(*)(K, const R&, void*)>(callback)(key, result, userData);
*static_cast<R*>(destination) = result; *static_cast<R*>(destination) = result;
}, &destination, reinterpret_cast<void(*)()>(callbackPtr), userData); }, &destination, reinterpret_cast<void(*)()>(callbackPtr), userData);
@ -862,7 +863,8 @@ template<class T, class K> template<class V, class R, class U, class Callback> P
[](const TrackViewStorage<const K>& track, K key, std::size_t& hint, void* destination, void(*callback)(), void* userData) { [](const TrackViewStorage<const K>& track, K key, std::size_t& hint, void* destination, void(*callback)(), void* userData) {
/** @todo try to use atStrict() if possible */ /** @todo try to use atStrict() if possible */
R result = static_cast<const TrackView<const K, const V, R>&>(track).at(key, hint); R result = static_cast<const TrackView<const K, const V, R>&>(track).at(key, hint);
if(result == *static_cast<R*>(destination)) return; if(result == *static_cast<R*>(destination))
return;
reinterpret_cast<void(*)(K, const R&, U&)>(callback)(key, result, *static_cast<U*>(userData)); reinterpret_cast<void(*)(K, const R&, U&)>(callback)(key, result, *static_cast<U*>(userData));
*static_cast<R*>(destination) = result; *static_cast<R*>(destination) = result;
}, &destination, reinterpret_cast<void(*)()>(callbackPtr), &userData); }, &destination, reinterpret_cast<void(*)()>(callbackPtr), &userData);

27
src/Magnum/Animation/Player.hpp

@ -74,7 +74,8 @@ template<class T, class K> struct Player<T, K>::Track {
#endif #endif
template<class T, class K> void Player<T, K>::advance(const T time, const std::initializer_list<Containers::Reference<Player<T, K>>> players) { template<class T, class K> void Player<T, K>::advance(const T time, const std::initializer_list<Containers::Reference<Player<T, K>>> players) {
for(Player<T, K>& p: players) p.advance(time); for(Player<T, K>& p: players)
p.advance(time);
} }
template<class T, class K> Player<T, K>::Player(Player<T, K>&&) noexcept = default; template<class T, class K> Player<T, K>::Player(Player<T, K>&&) noexcept = default;
@ -126,13 +127,15 @@ template<class T, class K> Player<T, K>& Player<T, K>::play(T startTime) {
} }
template<class T, class K> Player<T, K>& Player<T, K>::resume(T startTime) { template<class T, class K> Player<T, K>& Player<T, K>::resume(T startTime) {
if(_state == State::Playing) return *this; if(_state == State::Playing)
return *this;
return play(startTime); return play(startTime);
} }
template<class T, class K> Player<T, K>& Player<T, K>::pause(T pauseTime) { template<class T, class K> Player<T, K>& Player<T, K>::pause(T pauseTime) {
/* Avoid breaking the pause state when not playing */ /* Avoid breaking the pause state when not playing */
if(_state != State::Playing) return *this; if(_state != State::Playing)
return *this;
_state = State::Paused; _state = State::Paused;
_stopPauseTime = pauseTime; _stopPauseTime = pauseTime;
@ -141,7 +144,8 @@ template<class T, class K> Player<T, K>& Player<T, K>::pause(T pauseTime) {
template<class T, class K> Player<T, K>& Player<T, K>::seekBy(T timeDelta) { template<class T, class K> Player<T, K>& Player<T, K>::seekBy(T timeDelta) {
/* Animation is stopped, nothing to do */ /* Animation is stopped, nothing to do */
if(_state == State::Stopped) return *this; if(_state == State::Stopped)
return *this;
/* If the animation is paused and parked already, trigger a "park" again in /* If the animation is paused and parked already, trigger a "park" again in
order to have the values updated on the next call to advance(). The order to have the values updated on the next call to advance(). The
@ -160,7 +164,8 @@ template<class T, class K> Player<T, K>& Player<T, K>::seekBy(T timeDelta) {
template<class T, class K> Player<T, K>& Player<T, K>::seekTo(T seekTime, T animationTime) { template<class T, class K> Player<T, K>& Player<T, K>::seekTo(T seekTime, T animationTime) {
/* Animation is stopped, nothing to do */ /* Animation is stopped, nothing to do */
if(_state == State::Stopped) return *this; if(_state == State::Stopped)
return *this;
/* If the animation is paused and parked already, trigger a "park" again in /* If the animation is paused and parked already, trigger a "park" again in
order to have the values updated on the next call to advance(). The order to have the values updated on the next call to advance(). The
@ -233,7 +238,8 @@ template<class T, class K> Containers::Optional<std::pair<UnsignedInt, K>> playe
key = K{}; key = K{};
playIteration = 0; playIteration = 0;
if(playCount != 0) { if(playCount != 0) {
if(state != State::Paused) state = State::Stopped; if(state != State::Paused)
state = State::Stopped;
startTime = {}; startTime = {};
} }
@ -245,7 +251,8 @@ template<class T, class K> Containers::Optional<std::pair<UnsignedInt, K>> playe
playIteration = scaled.first; playIteration = scaled.first;
key = scaled.second; key = scaled.second;
if(playCount && playIteration >= playCount) { if(playCount && playIteration >= playCount) {
if(state != State::Paused) state = State::Stopped; if(state != State::Paused)
state = State::Stopped;
/* Don't reset the startTime to disambiguate between explicitly /* Don't reset the startTime to disambiguate between explicitly
stopped and "time run out" animation */ stopped and "time run out" animation */
playIteration = playCount - 1; playIteration = playCount - 1;
@ -268,7 +275,8 @@ template<class T, class K> std::pair<UnsignedInt, K> Player<T, K>::elapsed(const
T pauseTime = _stopPauseTime; T pauseTime = _stopPauseTime;
State state = _state; State state = _state;
const Containers::Optional<std::pair<UnsignedInt, K>> elapsed = Implementation::playerElapsed(duration, _playCount, _scaler, time, startTime, pauseTime, state); const Containers::Optional<std::pair<UnsignedInt, K>> elapsed = Implementation::playerElapsed(duration, _playCount, _scaler, time, startTime, pauseTime, state);
if(elapsed) return *elapsed; if(elapsed)
return *elapsed;
} }
/* If not advancing, the animation can be paused -- calculate the iteration /* If not advancing, the animation can be paused -- calculate the iteration
@ -300,7 +308,8 @@ template<class T, class K> Player<T, K>& Player<T, K>::advance(const T time) {
/* Get the elapsed time. If we shouldn't advance anything (player already /* Get the elapsed time. If we shouldn't advance anything (player already
stopped / not yet playing, quit */ stopped / not yet playing, quit */
Containers::Optional<std::pair<UnsignedInt, K>> elapsed = Implementation::playerElapsed(_duration.size(), _playCount, _scaler, time, _startTime, _stopPauseTime, _state); Containers::Optional<std::pair<UnsignedInt, K>> elapsed = Implementation::playerElapsed(_duration.size(), _playCount, _scaler, time, _startTime, _stopPauseTime, _state);
if(!elapsed) return *this; if(!elapsed)
return *this;
/* Advance all tracks. Properly handle durations that don't start at 0. */ /* Advance all tracks. Properly handle durations that don't start at 0. */
for(Track& t: _tracks) for(Track& t: _tracks)

3
src/Magnum/Animation/Test/PlayerTest.cpp

@ -1312,7 +1312,8 @@ template<class T> void PlayerTest::addRawCallback() {
[](const Animation::TrackViewStorage<const Float>& track, Float key, [](const Animation::TrackViewStorage<const Float>& track, Float key,
std::size_t& hint, void* destination, void(*callback)(), void* userData) { std::size_t& hint, void* destination, void(*callback)(), void* userData) {
Int value = static_cast<const Animation::TrackView<const Float, const Int>&>(track).at(key, hint); Int value = static_cast<const Animation::TrackView<const Float, const Int>&>(track).at(key, hint);
if(value == *static_cast<Int*>(destination)) return; if(value == *static_cast<Int*>(destination))
return;
*static_cast<Int*>(destination) = value; *static_cast<Int*>(destination) = value;
reinterpret_cast<void(*)(Containers::Array<Int>&, Int)>(callback)(*static_cast<Containers::Array<Int>*>(userData), value); reinterpret_cast<void(*)(Containers::Array<Int>&, Int)>(callback)(*static_cast<Containers::Array<Int>*>(userData), value);
}, &result, reinterpret_cast<void(*)()>(callback), &data) }, &result, reinterpret_cast<void(*)()>(callback), &data)

6
src/Magnum/Array.h

@ -110,7 +110,8 @@ template<UnsignedInt dimensions, class T> class CORRADE_DEPRECATED("use Math::Ve
/** @brief Equality */ /** @brief Equality */
bool operator==(const Array<dimensions, T>& other) const { bool operator==(const Array<dimensions, T>& other) const {
for(UnsignedInt i = 0; i != dimensions; ++i) for(UnsignedInt i = 0; i != dimensions; ++i)
if(_data[i] != other._data[i]) return false; if(_data[i] != other._data[i])
return false;
return true; return true;
} }
@ -257,7 +258,8 @@ template<class T> class CORRADE_DEPRECATED("use Math::Vector3 or Containers::Arr
template<UnsignedInt dimensions, class T> Debug& operator<<(Debug& debug, const Array<dimensions, T>& value) { template<UnsignedInt dimensions, class T> Debug& operator<<(Debug& debug, const Array<dimensions, T>& value) {
debug << "Array(" << Debug::nospace; debug << "Array(" << Debug::nospace;
for(UnsignedInt i = 0; i != dimensions; ++i) { for(UnsignedInt i = 0; i != dimensions; ++i) {
if(i != 0) debug << Debug::nospace << ","; if(i != 0)
debug << Debug::nospace << ",";
debug << value[i]; debug << value[i];
} }
return debug << Debug::nospace << ")"; return debug << Debug::nospace << ")";

5
src/Magnum/Audio/Buffer.h

@ -66,7 +66,10 @@ class MAGNUM_AUDIO_EXPORT Buffer {
* Deletes OpenAL buffer object. * Deletes OpenAL buffer object.
* @see @fn_al_keyword{DeleteBuffers} * @see @fn_al_keyword{DeleteBuffers}
*/ */
~Buffer() { if(_id) alDeleteBuffers(1, &_id); } ~Buffer() {
if(_id)
alDeleteBuffers(1, &_id);
}
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
Buffer(const Buffer&) = delete; Buffer(const Buffer&) = delete;

18
src/Magnum/Audio/Context.cpp

@ -202,7 +202,8 @@ Context::Context(NoCreateT, const Int argc, const char* const* const argv) noexc
} }
void Context::create(const Configuration& configuration) { void Context::create(const Configuration& configuration) {
if(!tryCreate(configuration)) std::exit(1); if(!tryCreate(configuration))
std::exit(1);
} }
bool Context::tryCreate(const Configuration& configuration) { bool Context::tryCreate(const Configuration& configuration) {
@ -301,7 +302,8 @@ bool Context::tryCreate(const Configuration& configuration) {
anything. If it is, set its status as unsupported but flip the anything. If it is, set its status as unsupported but flip the
corresponding bit in the disabled bitmap so we know it is corresponding bit in the disabled bitmap so we know it is
supported and only got disabled */ supported and only got disabled */
if(!_extensionStatus[found->index()]) continue; if(!_extensionStatus[found->index()])
continue;
_extensionStatus.set(found->index(), false); _extensionStatus.set(found->index(), false);
_disabledExtensions.set(found->index(), true); _disabledExtensions.set(found->index(), true);
@ -319,13 +321,17 @@ bool Context::tryCreate(const Configuration& configuration) {
Context::Context(Context&& other) noexcept: _device{other._device}, _context{other._context}, _extensionStatus{Utility::move(other._extensionStatus)}, _supportedExtensions{Utility::move(other._supportedExtensions)} { Context::Context(Context&& other) noexcept: _device{other._device}, _context{other._context}, _extensionStatus{Utility::move(other._extensionStatus)}, _supportedExtensions{Utility::move(other._supportedExtensions)} {
other._device = nullptr; other._device = nullptr;
other._context = nullptr; other._context = nullptr;
if(currentContext == &other) currentContext = this; if(currentContext == &other)
currentContext = this;
} }
Context::~Context() { Context::~Context() {
if(_context) alcDestroyContext(_context); if(_context)
if(_device) alcCloseDevice(_device); alcDestroyContext(_context);
if(currentContext == this) currentContext = nullptr; if(_device)
alcCloseDevice(_device);
if(currentContext == this)
currentContext = nullptr;
} }
std::vector<std::string> Context::extensionStrings() const { std::vector<std::string> Context::extensionStrings() const {

6
src/Magnum/Audio/Listener.cpp

@ -59,7 +59,8 @@ template<UnsignedInt dimensions> Listener<dimensions>::~Listener() = default;
template<UnsignedInt dimensions> void Listener<dimensions>::clean(const MatrixTypeFor<dimensions, Float>& absoluteTransformationMatrix) { template<UnsignedInt dimensions> void Listener<dimensions>::clean(const MatrixTypeFor<dimensions, Float>& absoluteTransformationMatrix) {
/* Only clean if this Listener is active */ /* Only clean if this Listener is active */
if(!isActive()) return; if(!isActive())
return;
Renderer::setListenerPosition(_soundTransformation.transformVector(Vector3::pad(absoluteTransformationMatrix.translation()))); Renderer::setListenerPosition(_soundTransformation.transformVector(Vector3::pad(absoluteTransformationMatrix.translation())));
@ -102,7 +103,8 @@ template<UnsignedInt dimensions> void Listener<dimensions>::update(std::initiali
template<UnsignedInt dimensions> Listener<dimensions>& Listener<dimensions>::setGain(const Float gain) { template<UnsignedInt dimensions> Listener<dimensions>& Listener<dimensions>::setGain(const Float gain) {
_gain = gain; _gain = gain;
if(isActive()) Renderer::setListenerGain(_gain); if(isActive())
Renderer::setListenerGain(_gain);
return *this; return *this;
} }

3
src/Magnum/Audio/Source.cpp

@ -54,7 +54,8 @@ std::size_t Source::unqueueBuffers(Containers::ArrayView<Containers::Reference<B
ALint processedBuffers; ALint processedBuffers;
alGetSourcei(_id, AL_BUFFERS_PROCESSED, &processedBuffers); alGetSourcei(_id, AL_BUFFERS_PROCESSED, &processedBuffers);
if(!processedBuffers) return 0; if(!processedBuffers)
return 0;
Containers::Array<ALuint> unqueuedIds(processedBuffers); Containers::Array<ALuint> unqueuedIds(processedBuffers);
alSourceUnqueueBuffers(_id, unqueuedIds.size(), unqueuedIds.data()); alSourceUnqueueBuffers(_id, unqueuedIds.size(), unqueuedIds.data());

5
src/Magnum/Audio/Source.h

@ -72,7 +72,10 @@ class MAGNUM_AUDIO_EXPORT Source {
* Deletes OpenAL source object. * Deletes OpenAL source object.
* @see @fn_al_keyword{DeleteSources} * @see @fn_al_keyword{DeleteSources}
*/ */
~Source() { if(_id) alDeleteSources(1, &_id); } ~Source() {
if(_id)
alDeleteSources(1, &_id);
}
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
Source(const Source&) = delete; Source(const Source&) = delete;

3
src/Magnum/Audio/Test/GlobalStateAcrossLibrariesLibrary.cpp

@ -31,7 +31,8 @@
namespace Magnum { namespace Audio { namespace Test { namespace Magnum { namespace Audio { namespace Test {
Audio::Context* currentContextInALibrary() { Audio::Context* currentContextInALibrary() {
if(!Audio::Context::hasCurrent()) return nullptr; if(!Audio::Context::hasCurrent())
return nullptr;
return &Audio::Context::current(); return &Audio::Context::current();
} }

3
src/Magnum/Audio/al-info.cpp

@ -174,7 +174,8 @@ int main(const int argc, const char* const* const argv) {
return 0; return 0;
} }
if(args.isSet("short")) return 0; if(args.isSet("short"))
return 0;
Debug() << "Vendor extension support:"; Debug() << "Vendor extension support:";
for(const auto& extension: Audio::Extension::extensions()) { for(const auto& extension: Audio::Extension::extensions()) {

3
src/Magnum/DebugTools/BufferData.h

@ -109,7 +109,8 @@ template<class T> CORRADE_DEPRECATED("use non-templated bufferSubData() and Cont
/* Yes, this should have NoInit, but let's preserve the deprecated API in /* Yes, this should have NoInit, but let's preserve the deprecated API in
its original form */ its original form */
Containers::Array<T> data{std::size_t(size)}; Containers::Array<T> data{std::size_t(size)};
if(size) Implementation::bufferSubData(buffer, offset, size*sizeof(T), data); if(size)
Implementation::bufferSubData(buffer, offset, size*sizeof(T), data);
return data; return data;
} }
#endif #endif

18
src/Magnum/DebugTools/CompareImage.cpp

@ -252,7 +252,8 @@ void printDeltaImage(Debug& out, Containers::ArrayView<const Float> deltas, cons
const Vector2i blockCount = (size + pixelsPerBlock - Vector2i{1})/pixelsPerBlock; const Vector2i blockCount = (size + pixelsPerBlock - Vector2i{1})/pixelsPerBlock;
for(std::int_fast32_t y = 0; y != blockCount.y(); ++y) { for(std::int_fast32_t y = 0; y != blockCount.y(); ++y) {
if(y) out << Debug::newline; if(y)
out << Debug::newline;
out << " |"; out << " |";
for(std::int_fast32_t x = 0; x != blockCount.x(); ++x) { for(std::int_fast32_t x = 0; x != blockCount.x(); ++x) {
@ -388,11 +389,13 @@ void printPixelDeltas(Debug& out, Containers::ArrayView<const Float> delta, Pixe
sorted map. Need to reverse the condition in order to catch NaNs. */ sorted map. Need to reverse the condition in order to catch NaNs. */
std::multimap<Float, std::size_t> large; std::multimap<Float, std::size_t> large;
for(std::size_t i = 0; i != delta.size(); ++i) for(std::size_t i = 0; i != delta.size(); ++i)
if(!(delta[i] <= meanThreshold)) large.emplace(delta[i], i); if(!(delta[i] <= meanThreshold))
large.emplace(delta[i], i);
/* If there's no outliers, don't print anything. This can happen only when /* If there's no outliers, don't print anything. This can happen only when
--verbose is used. */ --verbose is used. */
if(large.empty()) return; if(large.empty())
return;
/* If there are outliers, adding a newline to separate itself from the /* If there are outliers, adding a newline to separate itself from the
delta image -- calling code wouldn't know if we produce output or not, delta image -- calling code wouldn't know if we produce output or not,
@ -408,7 +411,8 @@ void printPixelDeltas(Debug& out, Containers::ArrayView<const Float> delta, Pixe
inner loop but that doesn't matter as we always print just ~10 values. */ inner loop but that doesn't matter as we always print just ~10 values. */
std::size_t count = 0; std::size_t count = 0;
for(auto it = large.crbegin(); it != large.crend(); ++it) { for(auto it = large.crbegin(); it != large.crend(); ++it) {
if(++count > maxCount) break; if(++count > maxCount)
break;
const Containers::Pair<Int, Int> div = Math::div(Int(it->second), Int(expectedPixels.size()[1])); const Containers::Pair<Int, Int> div = Math::div(Int(it->second), Int(expectedPixels.size()[1]));
const Vector2i pos{div.second(), div.first()}; const Vector2i pos{div.second(), div.first()};
@ -457,11 +461,13 @@ class ImageComparatorBase::State {
the --save-failed option. Treat both the same lazy way to keep the the --save-failed option. Treat both the same lazy way to keep the
code straightforward. */ code straightforward. */
PluginManager::Manager<Trade::AbstractImporter>& importerManager() { PluginManager::Manager<Trade::AbstractImporter>& importerManager() {
if(!_importerManager) _importerManager = &_privateImporterManager.emplace(); if(!_importerManager)
_importerManager = &_privateImporterManager.emplace();
return *_importerManager; return *_importerManager;
} }
PluginManager::Manager<Trade::AbstractImageConverter>& converterManager() { PluginManager::Manager<Trade::AbstractImageConverter>& converterManager() {
if(!_converterManager) _converterManager = &_privateConverterManager.emplace(); if(!_converterManager)
_converterManager = &_privateConverterManager.emplace();
return *_converterManager; return *_converterManager;
} }

6
src/Magnum/DebugTools/CompareMaterial.cpp

@ -297,9 +297,11 @@ void Comparator<DebugTools::CompareMaterial>::printMessage(const TestSuite::Comp
} }
if(_state->actual->types() && _state->actual->types() != _state->expected->types()) { if(_state->actual->types() && _state->actual->types() != _state->expected->types()) {
out << Debug::newline << " " << Debug::color(Debug::Color::Green) << "+" << Debug::nospace; out << Debug::newline << " " << Debug::color(Debug::Color::Green) << "+" << Debug::nospace;
if(_state->expected->types()) out << Debug::resetColor; if(_state->expected->types())
out << Debug::resetColor;
out << "Types:"; out << "Types:";
if(_state->expected->types()) out << Debug::color(Debug::Color::Green); if(_state->expected->types())
out << Debug::color(Debug::Color::Green);
out << Debug::packed << _state->actual->types() << Debug::resetColor; out << Debug::packed << _state->actual->types() << Debug::resetColor;
} }

6
src/Magnum/DebugTools/ForceRenderer.cpp

@ -74,11 +74,13 @@ constexpr UnsignedByte indices[]{
template<UnsignedInt dimensions> ForceRenderer<dimensions>::ForceRenderer(ResourceManager& manager, SceneGraph::AbstractObject<dimensions, Float>& object, const VectorTypeFor<dimensions, Float>& forcePosition, const VectorTypeFor<dimensions, Float>& force, ResourceKey options, SceneGraph::DrawableGroup<dimensions, Float>* drawables): SceneGraph::Drawable<dimensions, Float>(object, drawables), _forcePosition(forcePosition), _force(force), _options(manager.get<ForceRendererOptions>(options)) { template<UnsignedInt dimensions> ForceRenderer<dimensions>::ForceRenderer(ResourceManager& manager, SceneGraph::AbstractObject<dimensions, Float>& object, const VectorTypeFor<dimensions, Float>& forcePosition, const VectorTypeFor<dimensions, Float>& force, ResourceKey options, SceneGraph::DrawableGroup<dimensions, Float>* drawables): SceneGraph::Drawable<dimensions, Float>(object, drawables), _forcePosition(forcePosition), _force(force), _options(manager.get<ForceRendererOptions>(options)) {
/* Shader */ /* Shader */
_shader = manager.get<GL::AbstractShaderProgram, Shaders::FlatGL<dimensions>>(shaderKey<dimensions>()); _shader = manager.get<GL::AbstractShaderProgram, Shaders::FlatGL<dimensions>>(shaderKey<dimensions>());
if(!_shader) manager.set<GL::AbstractShaderProgram>(_shader.key(), new Shaders::FlatGL<dimensions>); if(!_shader)
manager.set<GL::AbstractShaderProgram>(_shader.key(), new Shaders::FlatGL<dimensions>);
/* Mesh and vertex buffer */ /* Mesh and vertex buffer */
_mesh = manager.get<GL::Mesh>("force"); _mesh = manager.get<GL::Mesh>("force");
if(_mesh) return; if(_mesh)
return;
/* Create the mesh */ /* Create the mesh */
GL::Buffer vertexBuffer{GL::Buffer::TargetHint::Array}; GL::Buffer vertexBuffer{GL::Buffer::TargetHint::Array};

39
src/Magnum/DebugTools/FrameProfiler.cpp

@ -79,7 +79,8 @@ FrameProfiler::FrameProfiler(FrameProfiler&& other) noexcept:
/* For all state pointers that point to &other patch them to point to this /* For all state pointers that point to &other patch them to point to this
instead, to account for 90% of use cases of derived classes */ instead, to account for 90% of use cases of derived classes */
for(Measurement& measurement: _measurements) for(Measurement& measurement: _measurements)
if(measurement._state == &other) measurement._state = this; if(measurement._state == &other)
measurement._state = this;
} }
FrameProfiler& FrameProfiler::operator=(FrameProfiler&& other) noexcept { FrameProfiler& FrameProfiler::operator=(FrameProfiler&& other) noexcept {
@ -96,12 +97,14 @@ FrameProfiler& FrameProfiler::operator=(FrameProfiler&& other) noexcept {
/* For all state pointers that point to &other patch them to point to this /* For all state pointers that point to &other patch them to point to this
instead, to account for 90% of use cases of derived classes */ instead, to account for 90% of use cases of derived classes */
for(Measurement& measurement: _measurements) for(Measurement& measurement: _measurements)
if(measurement._state == &other) measurement._state = this; if(measurement._state == &other)
measurement._state = this;
/* And the same the other way to avoid the other instance accidentally /* And the same the other way to avoid the other instance accidentally
affecting our measurements */ affecting our measurements */
for(Measurement& measurement: other._measurements) for(Measurement& measurement: other._measurements)
if(measurement._state == this) measurement._state = &other; if(measurement._state == this)
measurement._state = &other;
return *this; return *this;
} }
@ -360,7 +363,8 @@ void FrameProfiler::printStatisticsInternal(Debug& out) const {
out << Debug::color(Debug::Color::Blue) << "-.--" out << Debug::color(Debug::Color::Blue) << "-.--"
<< Debug::resetColor; << Debug::resetColor;
if(units[0] != '\0') out << units; if(units[0] != '\0')
out << units;
/* Otherwise format the value */ /* Otherwise format the value */
} else { } else {
@ -406,7 +410,8 @@ Containers::String FrameProfiler::statistics() const {
void FrameProfiler::printStatistics(const UnsignedInt frequency) const { void FrameProfiler::printStatistics(const UnsignedInt frequency) const {
Debug::Flags flags; Debug::Flags flags;
if(!Debug::isTty()) flags |= Debug::Flag::DisableColors; if(!Debug::isTty())
flags |= Debug::Flag::DisableColors;
printStatistics(Debug{flags}, frequency); printStatistics(Debug{flags}, frequency);
} }
@ -559,7 +564,8 @@ void FrameProfilerGL::setup(const Values values, const UnsignedInt maxFrameCount
[](void* state, UnsignedInt previous, UnsignedInt) { [](void* state, UnsignedInt previous, UnsignedInt) {
/* Avoid division by zero if a frame doesn't have any draws */ /* Avoid division by zero if a frame doesn't have any draws */
const auto submitted = static_cast<State*>(state)->verticesSubmittedQueries[previous].result<UnsignedLong>(); const auto submitted = static_cast<State*>(state)->verticesSubmittedQueries[previous].result<UnsignedLong>();
if(!submitted) return UnsignedLong{}; if(!submitted)
return UnsignedLong{};
return static_cast<State*>(state)->vertexShaderInvocationsQueries[previous].result<UnsignedLong>()*1000/submitted; return static_cast<State*>(state)->vertexShaderInvocationsQueries[previous].result<UnsignedLong>()*1000/submitted;
}, _state.get()); }, _state.get());
@ -584,14 +590,16 @@ void FrameProfilerGL::setup(const Values values, const UnsignedInt maxFrameCount
[](void* state, UnsignedInt previous, UnsignedInt) { [](void* state, UnsignedInt previous, UnsignedInt) {
/* Avoid division by zero if a frame doesn't have any draws */ /* Avoid division by zero if a frame doesn't have any draws */
const auto input = static_cast<State*>(state)->clippingInputPrimitivesQueries[previous].result<UnsignedLong>(); const auto input = static_cast<State*>(state)->clippingInputPrimitivesQueries[previous].result<UnsignedLong>();
if(!input) return UnsignedLong{}; if(!input)
return UnsignedLong{};
/* If we have more output primitives than input, it's because /* If we have more output primitives than input, it's because
a triangle got split into multiple. To avoid an underflow, a triangle got split into multiple. To avoid an underflow,
return zero as well. A corresponding test case is in return zero as well. A corresponding test case is in
FrameProfilerGLTest::primitiveClipRatioNegative(). */ FrameProfilerGLTest::primitiveClipRatioNegative(). */
const auto output = static_cast<State*>(state)->clippingOutputPrimitivesQueries[previous].result<UnsignedLong>(); const auto output = static_cast<State*>(state)->clippingOutputPrimitivesQueries[previous].result<UnsignedLong>();
if(input < output) return UnsignedLong{}; if(input < output)
return UnsignedLong{};
return 100000 - static_cast<State*>(state)->clippingOutputPrimitivesQueries[previous].result<UnsignedLong>()*100000/input; return 100000 - static_cast<State*>(state)->clippingOutputPrimitivesQueries[previous].result<UnsignedLong>()*100000/input;
}, _state.get()); }, _state.get());
@ -603,12 +611,17 @@ void FrameProfilerGL::setup(const Values values, const UnsignedInt maxFrameCount
auto FrameProfilerGL::values() const -> Values { auto FrameProfilerGL::values() const -> Values {
Values values; Values values;
if(_state->frameTimeIndex != 0xffff) values |= Value::FrameTime; if(_state->frameTimeIndex != 0xffff)
if(_state->cpuDurationIndex != 0xffff) values |= Value::CpuDuration; values |= Value::FrameTime;
if(_state->gpuDurationIndex != 0xffff) values |= Value::GpuDuration; if(_state->cpuDurationIndex != 0xffff)
values |= Value::CpuDuration;
if(_state->gpuDurationIndex != 0xffff)
values |= Value::GpuDuration;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(_state->vertexFetchRatioIndex != 0xffff) values |= Value::VertexFetchRatio; if(_state->vertexFetchRatioIndex != 0xffff)
if(_state->primitiveClipRatioIndex != 0xffff) values |= Value::PrimitiveClipRatio; values |= Value::VertexFetchRatio;
if(_state->primitiveClipRatioIndex != 0xffff)
values |= Value::PrimitiveClipRatio;
#endif #endif
return values; return values;
} }

6
src/Magnum/DebugTools/ObjectRenderer.cpp

@ -72,11 +72,13 @@ template<> struct Renderer<3> {
template<UnsignedInt dimensions> ObjectRenderer<dimensions>::ObjectRenderer(ResourceManager& manager, SceneGraph::AbstractObject<dimensions, Float>& object, ResourceKey options, SceneGraph::DrawableGroup<dimensions, Float>* drawables): SceneGraph::Drawable<dimensions, Float>{object, drawables}, _options{manager.get<ObjectRendererOptions>(options)} { template<UnsignedInt dimensions> ObjectRenderer<dimensions>::ObjectRenderer(ResourceManager& manager, SceneGraph::AbstractObject<dimensions, Float>& object, ResourceKey options, SceneGraph::DrawableGroup<dimensions, Float>* drawables): SceneGraph::Drawable<dimensions, Float>{object, drawables}, _options{manager.get<ObjectRendererOptions>(options)} {
/* Shader */ /* Shader */
_shader = manager.get<GL::AbstractShaderProgram, Shaders::VertexColorGL<dimensions>>(Renderer<dimensions>::shader()); _shader = manager.get<GL::AbstractShaderProgram, Shaders::VertexColorGL<dimensions>>(Renderer<dimensions>::shader());
if(!_shader) manager.set<GL::AbstractShaderProgram>(_shader.key(), new Shaders::VertexColorGL<dimensions>); if(!_shader)
manager.set<GL::AbstractShaderProgram>(_shader.key(), new Shaders::VertexColorGL<dimensions>);
/* Mesh */ /* Mesh */
_mesh = manager.get<GL::Mesh>(Renderer<dimensions>::mesh()); _mesh = manager.get<GL::Mesh>(Renderer<dimensions>::mesh());
if(!_mesh) manager.set<GL::Mesh>(_mesh.key(), MeshTools::compile(Renderer<dimensions>::meshData())); if(!_mesh)
manager.set<GL::Mesh>(_mesh.key(), MeshTools::compile(Renderer<dimensions>::meshData()));
} }
/* To avoid deleting pointers to incomplete type on destruction of Resource members */ /* To avoid deleting pointers to incomplete type on destruction of Resource members */

15
src/Magnum/DebugTools/Profiler.cpp

@ -68,7 +68,8 @@ void Profiler::disable() {
/* MSVC complains about deprecated Section here */ /* MSVC complains about deprecated Section here */
CORRADE_IGNORE_DEPRECATED_PUSH CORRADE_IGNORE_DEPRECATED_PUSH
void Profiler::start(Section section) { void Profiler::start(Section section) {
if(!_enabled) return; if(!_enabled)
return;
CORRADE_ASSERT(section < _sections.size(), "Profiler: unknown section passed to start()", ); CORRADE_ASSERT(section < _sections.size(), "Profiler: unknown section passed to start()", );
save(); save();
@ -78,7 +79,8 @@ void Profiler::start(Section section) {
CORRADE_IGNORE_DEPRECATED_POP CORRADE_IGNORE_DEPRECATED_POP
void Profiler::stop() { void Profiler::stop() {
if(!_enabled) return; if(!_enabled)
return;
save(); save();
@ -97,7 +99,8 @@ void Profiler::save() {
} }
void Profiler::nextFrame() { void Profiler::nextFrame() {
if(!_enabled) return; if(!_enabled)
return;
/* Next frame index */ /* Next frame index */
std::size_t nextFrame = (_currentFrame+1) % _measureDuration; std::size_t nextFrame = (_currentFrame+1) % _measureDuration;
@ -115,11 +118,13 @@ void Profiler::nextFrame() {
/* Advance to next frame */ /* Advance to next frame */
_currentFrame = nextFrame; _currentFrame = nextFrame;
if(_frameCount < _measureDuration) ++_frameCount; if(_frameCount < _measureDuration)
++_frameCount;
} }
void Profiler::printStatistics() { void Profiler::printStatistics() {
if(!_enabled) return; if(!_enabled)
return;
std::vector<std::size_t> totalSorted(_sections.size()); std::vector<std::size_t> totalSorted(_sections.size());
std::iota(totalSorted.begin(), totalSorted.end(), 0); std::iota(totalSorted.begin(), totalSorted.end(), 0);

3
src/Magnum/DebugTools/Test/FrameProfilerGLTest.cpp

@ -134,7 +134,8 @@ void FrameProfilerGLTest::test() {
FrameProfilerGL::Value::PrimitiveClipRatio FrameProfilerGL::Value::PrimitiveClipRatio
#endif #endif
}) { }) {
if(!(data.values & value)) continue; if(!(data.values & value))
continue;
CORRADE_VERIFY(!profiler.isMeasurementAvailable(value)); CORRADE_VERIFY(!profiler.isMeasurementAvailable(value));
/* The names should not be allocated */ /* The names should not be allocated */

21
src/Magnum/GL/AbstractShaderProgram.cpp

@ -312,7 +312,8 @@ AbstractShaderProgram::~AbstractShaderProgram() {
/* Remove current usage from the state */ /* Remove current usage from the state */
GLuint& current = Context::current().state().shaderProgram.current; GLuint& current = Context::current().state().shaderProgram.current;
if(current == _id) current = 0; if(current == _id)
current = 0;
glDeleteProgram(_id); glDeleteProgram(_id);
} }
@ -587,7 +588,8 @@ AbstractShaderProgram& AbstractShaderProgram::dispatchComputeIndirect(Buffer& in
void AbstractShaderProgram::use(const GLuint id) { void AbstractShaderProgram::use(const GLuint id) {
/* Use only if the program isn't already in use */ /* Use only if the program isn't already in use */
GLuint& current = Context::current().state().shaderProgram.current; GLuint& current = Context::current().state().shaderProgram.current;
if(current != id) glUseProgram(current = id); if(current != id)
glUseProgram(current = id);
} }
void AbstractShaderProgram::use() { use(_id); } void AbstractShaderProgram::use() { use(_id); }
@ -597,7 +599,8 @@ void AbstractShaderProgram::attachShader(Shader& shader) {
} }
void AbstractShaderProgram::attachShaders(const Containers::Iterable<Shader>& shaders) { void AbstractShaderProgram::attachShaders(const Containers::Iterable<Shader>& shaders) {
for(Shader& s: shaders) attachShader(s); for(Shader& s: shaders)
attachShader(s);
} }
void AbstractShaderProgram::bindAttributeLocation(const UnsignedInt location, const Containers::StringView name) { void AbstractShaderProgram::bindAttributeLocation(const UnsignedInt location, const Containers::StringView name) {
@ -728,9 +731,11 @@ bool AbstractShaderProgram::checkLink(const Containers::Iterable<Shader>& shader
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
bool AbstractShaderProgram::link(std::initializer_list<Containers::Reference<AbstractShaderProgram>> shaders) { bool AbstractShaderProgram::link(std::initializer_list<Containers::Reference<AbstractShaderProgram>> shaders) {
for(AbstractShaderProgram& shader: shaders) shader.submitLink(); for(AbstractShaderProgram& shader: shaders)
shader.submitLink();
bool allSuccess = true; bool allSuccess = true;
for(AbstractShaderProgram& shader: shaders) allSuccess = allSuccess && shader.checkLink({}); for(AbstractShaderProgram& shader: shaders)
allSuccess = allSuccess && shader.checkLink({});
return allSuccess; return allSuccess;
} }
#endif #endif
@ -745,13 +750,15 @@ void AbstractShaderProgram::cleanLogImplementationNoOp(Containers::String&) {}
#if defined(CORRADE_TARGET_WINDOWS) && !defined(MAGNUM_TARGET_GLES) #if defined(CORRADE_TARGET_WINDOWS) && !defined(MAGNUM_TARGET_GLES)
void AbstractShaderProgram::cleanLogImplementationIntelWindows(Containers::String& message) { void AbstractShaderProgram::cleanLogImplementationIntelWindows(Containers::String& message) {
if(message == "No errors.\n") message = {}; if(message == "No errors.\n")
message = {};
} }
#endif #endif
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL)
void AbstractShaderProgram::cleanLogImplementationAngle(Containers::String& message) { void AbstractShaderProgram::cleanLogImplementationAngle(Containers::String& message) {
if(message == "\n") message = {}; if(message == "\n")
message = {};
} }
#endif #endif

18
src/Magnum/GL/AbstractTexture.cpp

@ -184,7 +184,8 @@ void AbstractTexture::bindImplementationMulti(const GLint firstTextureUnit, cons
const GLuint id = textures && textures[i] ? textures[i]->_id : 0; const GLuint id = textures && textures[i] ? textures[i]->_id : 0;
if(textures) { if(textures) {
if(textures[i]) textures[i]->createIfNotAlready(); if(textures[i])
textures[i]->createIfNotAlready();
ids[i] = id; ids[i] = id;
} }
@ -195,7 +196,8 @@ void AbstractTexture::bindImplementationMulti(const GLint firstTextureUnit, cons
} }
/* Avoid doing the binding if there is nothing different */ /* Avoid doing the binding if there is nothing different */
if(different) glBindTextures(firstTextureUnit, textures.size(), ids); if(different)
glBindTextures(firstTextureUnit, textures.size(), ids);
} }
#endif #endif
@ -240,14 +242,16 @@ AbstractTexture::~AbstractTexture() {
/* Remove all bindings */ /* Remove all bindings */
for(auto& binding: Context::current().state().texture.bindings) { for(auto& binding: Context::current().state().texture.bindings) {
/* MSVC 2015 needs the parentheses around */ /* MSVC 2015 needs the parentheses around */
if(binding.second() == _id) binding = {}; if(binding.second() == _id)
binding = {};
} }
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/* Remove all image bindings */ /* Remove all image bindings */
for(auto& binding: Context::current().state().texture.imageBindings) { for(auto& binding: Context::current().state().texture.imageBindings) {
/* MSVC 2015 needs the parentheses around */ /* MSVC 2015 needs the parentheses around */
if(binding.id == _id) binding = {}; if(binding.id == _id)
binding = {};
} }
#endif #endif
@ -334,7 +338,8 @@ void AbstractTexture::bindImages(const Int firstImageUnit, const Containers::Arr
} }
/* Avoid doing the binding if there is nothing different */ /* Avoid doing the binding if there is nothing different */
if(different) glBindImageTextures(firstImageUnit, textures.size(), ids); if(different)
glBindImageTextures(firstImageUnit, textures.size(), ids);
} }
void AbstractTexture::bindImages(const Int firstImageUnit, const std::initializer_list<AbstractTexture*> textures) { void AbstractTexture::bindImages(const Int firstImageUnit, const std::initializer_list<AbstractTexture*> textures) {
@ -401,7 +406,8 @@ void AbstractTexture::bindImplementationDSA(AbstractTexture& self, const GLint t
#ifdef CORRADE_TARGET_WINDOWS #ifdef CORRADE_TARGET_WINDOWS
void AbstractTexture::bindImplementationDSAIntelWindows(AbstractTexture& self, const GLint textureUnit) { void AbstractTexture::bindImplementationDSAIntelWindows(AbstractTexture& self, const GLint textureUnit) {
/* See the "intel-windows-half-baked-dsa-texture-bind" workaround */ /* See the "intel-windows-half-baked-dsa-texture-bind" workaround */
if(self._target == GL_TEXTURE_CUBE_MAP) bindImplementationDefault(self, textureUnit); if(self._target == GL_TEXTURE_CUBE_MAP)
bindImplementationDefault(self, textureUnit);
else bindImplementationDSA(self, textureUnit); else bindImplementationDSA(self, textureUnit);
} }
#endif #endif

6
src/Magnum/GL/Attribute.cpp

@ -227,7 +227,8 @@ UnsignedInt Attribute<Math::Vector<3, Float>>::size(GLint components, DataType d
UnsignedInt Attribute<Math::Vector<4, Float>>::size(GLint components, DataType dataType) { UnsignedInt Attribute<Math::Vector<4, Float>>::size(GLint components, DataType dataType) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(components == GL_BGRA) components = 4; if(components == GL_BGRA)
components = 4;
#endif #endif
switch(dataType) { switch(dataType) {
@ -586,7 +587,8 @@ namespace {
UnsignedInt attributeSize(DynamicAttribute::Components components, DynamicAttribute::DataType dataType) { UnsignedInt attributeSize(DynamicAttribute::Components components, DynamicAttribute::DataType dataType) {
Int componentCount = GLint(components); Int componentCount = GLint(components);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(components == DynamicAttribute::Components::BGRA) componentCount = 4; if(components == DynamicAttribute::Components::BGRA)
componentCount = 4;
#endif #endif
switch(dataType) { switch(dataType) {

12
src/Magnum/GL/Buffer.cpp

@ -209,7 +209,8 @@ Buffer::~Buffer() {
/* Remove all current bindings from the state */ /* Remove all current bindings from the state */
for(std::size_t i = 1; i != Implementation::BufferState::TargetCount; ++i) for(std::size_t i = 1; i != Implementation::BufferState::TargetCount; ++i)
if(bindings[i] == _id) bindings[i] = 0; if(bindings[i] == _id)
bindings[i] = 0;
glDeleteBuffers(1, &_id); glDeleteBuffers(1, &_id);
} }
@ -287,7 +288,8 @@ void Buffer::bindInternal(const TargetHint target, Buffer* const buffer) {
/* Bind the buffer otherwise, which will also finally create it */ /* Bind the buffer otherwise, which will also finally create it */
bound = id; bound = id;
if(buffer) buffer->_flags |= ObjectFlag::Created; if(buffer)
buffer->_flags |= ObjectFlag::Created;
glBindBuffer(GLenum(target), id); glBindBuffer(GLenum(target), id);
} }
@ -438,7 +440,8 @@ bool Buffer::unmap() { return Context::current().state().buffer.unmapImplementat
#if !defined(MAGNUM_TARGET_GLES) || (defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20017) #if !defined(MAGNUM_TARGET_GLES) || (defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20017)
Containers::Array<char> Buffer::subData(const GLintptr offset, const GLsizeiptr size) { Containers::Array<char> Buffer::subData(const GLintptr offset, const GLsizeiptr size) {
Containers::Array<char> data{NoInit, std::size_t(size)}; Containers::Array<char> data{NoInit, std::size_t(size)};
if(size) Context::current().state().buffer.getSubDataImplementation(*this, offset, size, data); if(size)
Context::current().state().buffer.getSubDataImplementation(*this, offset, size, data);
return data; return data;
} }
#endif #endif
@ -446,7 +449,8 @@ Containers::Array<char> Buffer::subData(const GLintptr offset, const GLsizeiptr
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void Buffer::bindImplementationFallback(const Target target, const GLuint firstIndex, Containers::ArrayView<Buffer* const> buffers) { void Buffer::bindImplementationFallback(const Target target, const GLuint firstIndex, Containers::ArrayView<Buffer* const> buffers) {
for(std::size_t i = 0; i != buffers.size(); ++i) { for(std::size_t i = 0; i != buffers.size(); ++i) {
if(buffers && buffers[i]) buffers[i]->bind(target, firstIndex + i); if(buffers && buffers[i])
buffers[i]->bind(target, firstIndex + i);
else unbind(target, firstIndex + i); else unbind(target, firstIndex + i);
} }
} }

18
src/Magnum/GL/Context.cpp

@ -843,16 +843,19 @@ Context::Context(Context&& other) noexcept:
_configurationFlags{other._configurationFlags} _configurationFlags{other._configurationFlags}
{ {
Utility::copy(other._extensionRequiredVersion, _extensionRequiredVersion); Utility::copy(other._extensionRequiredVersion, _extensionRequiredVersion);
if(currentContext == &other) currentContext = this; if(currentContext == &other)
currentContext = this;
} }
Context::~Context() { Context::~Context() {
if(currentContext == this) currentContext = nullptr; if(currentContext == this)
currentContext = nullptr;
} }
void Context::create(const Configuration& configuration) { void Context::create(const Configuration& configuration) {
/* Hard exit if the context cannot be created */ /* Hard exit if the context cannot be created */
if(!tryCreate(configuration)) std::exit(1); if(!tryCreate(configuration))
std::exit(1);
} }
bool Context::tryCreate(const Configuration& configuration) { bool Context::tryCreate(const Configuration& configuration) {
@ -892,7 +895,8 @@ bool Context::tryCreate(const Configuration& configuration) {
/* Load GL function pointers. Pass this instance to it so it can use it for /* Load GL function pointers. Pass this instance to it so it can use it for
potential driver-specific workarounds. */ potential driver-specific workarounds. */
if(_functionLoader) _functionLoader(*this); if(_functionLoader)
_functionLoader(*this);
/* Initialize to something predictable to avoid crashes on improperly /* Initialize to something predictable to avoid crashes on improperly
created contexts */ created contexts */
@ -1024,7 +1028,8 @@ bool Context::tryCreate(const Configuration& configuration) {
} }
/* Reset minimal required version to Version::None for whole array */ /* Reset minimal required version to Version::None for whole array */
for(auto& i: _extensionRequiredVersion) i = Version::None; for(auto& i: _extensionRequiredVersion)
i = Version::None;
/* Initialize required versions from extension info */ /* Initialize required versions from extension info */
for(const auto& version: KnownExtensionsForVersion) for(const auto& version: KnownExtensionsForVersion)
@ -1072,7 +1077,8 @@ bool Context::tryCreate(const Configuration& configuration) {
if(!_driverWorkarounds.isEmpty()) { if(!_driverWorkarounds.isEmpty()) {
Debug{output} << "Using driver workarounds:"; Debug{output} << "Using driver workarounds:";
for(const auto& workaround: _driverWorkarounds) for(const auto& workaround: _driverWorkarounds)
if(!workaround.second()) Debug(output) << " " << workaround.first(); if(!workaround.second())
Debug(output) << " " << workaround.first();
} }
/* Fetch default framebuffer size and set up default clear color. If we are /* Fetch default framebuffer size and set up default clear color. If we are

5
src/Magnum/GL/DebugOutput.h

@ -749,7 +749,10 @@ class MAGNUM_GL_EXPORT DebugGroup {
* *
* If the group is active, calls @ref pop(). * If the group is active, calls @ref pop().
*/ */
~DebugGroup() { if(_active) pop(); } ~DebugGroup() {
if(_active)
pop();
}
/** /**
* @brief Push debug group onto the stack * @brief Push debug group onto the stack

4
src/Magnum/GL/DefaultFramebuffer.cpp

@ -64,8 +64,8 @@ DefaultFramebuffer& DefaultFramebuffer::clearColor(const Vector4ui& color) {
DefaultFramebuffer& DefaultFramebuffer::mapForDraw(const Containers::ArrayView<const Containers::Pair<UnsignedInt, DrawAttachment>> attachments) { DefaultFramebuffer& DefaultFramebuffer::mapForDraw(const Containers::ArrayView<const Containers::Pair<UnsignedInt, DrawAttachment>> attachments) {
/* Max attachment location */ /* Max attachment location */
std::size_t max = 0; std::size_t max = 0;
for(const auto& attachment: attachments) for(const auto& attachment: attachments) if(attachment.first() > max)
if(attachment.first() > max) max = attachment.first(); max = attachment.first();
/* Create linear array from associative */ /* Create linear array from associative */
/** @todo C++14: use VLA to avoid heap allocation */ /** @todo C++14: use VLA to avoid heap allocation */

7
src/Magnum/GL/Framebuffer.cpp

@ -131,7 +131,8 @@ Framebuffer::~Framebuffer() {
/* If bound, remove itself from state */ /* If bound, remove itself from state */
Context& context = Context::current(); Context& context = Context::current();
Implementation::FramebufferState& state = context.state().framebuffer; Implementation::FramebufferState& state = context.state().framebuffer;
if(state.readBinding == _id) state.readBinding = 0; if(state.readBinding == _id)
state.readBinding = 0;
/* For draw binding reset also viewport. Don't do that for windowless /* For draw binding reset also viewport. Don't do that for windowless
contexts to avoid potential race conditions with default framebuffer on contexts to avoid potential race conditions with default framebuffer on
@ -188,8 +189,8 @@ Framebuffer& Framebuffer::clearColor(const Int attachment, const Vector4ui& colo
Framebuffer& Framebuffer::mapForDraw(const Containers::ArrayView<const Containers::Pair<UnsignedInt, DrawAttachment>> attachments) { Framebuffer& Framebuffer::mapForDraw(const Containers::ArrayView<const Containers::Pair<UnsignedInt, DrawAttachment>> attachments) {
/* Max attachment location */ /* Max attachment location */
std::size_t max = 0; std::size_t max = 0;
for(const auto& attachment: attachments) for(const auto& attachment: attachments) if(attachment.first() > max)
if(attachment.first() > max) max = attachment.first(); max = attachment.first();
/* Create linear array from associative */ /* Create linear array from associative */
/** @todo C++14: use VLA to avoid heap allocation */ /** @todo C++14: use VLA to avoid heap allocation */

3
src/Magnum/GL/Implementation/BufferState.cpp

@ -240,7 +240,8 @@ BufferState::BufferState(Context& context, Containers::StaticArrayView<Implement
} }
void BufferState::reset() { void BufferState::reset() {
for(GLuint& i: bindings) i = State::DisengagedBinding; for(GLuint& i: bindings)
i = State::DisengagedBinding;
} }
}}} }}}

6
src/Magnum/GL/Implementation/MeshState.cpp

@ -544,8 +544,10 @@ MeshState::~MeshState() {
/* If the default VAO was created, we need to delete it to avoid leaks. /* If the default VAO was created, we need to delete it to avoid leaks.
Delete also the scratch VAO if the engine was so unlucky to have to run Delete also the scratch VAO if the engine was so unlucky to have to run
awful external GL code (it was created in Context::resetState()). */ awful external GL code (it was created in Context::resetState()). */
if(defaultVAO) glDeleteVertexArrays(1, &defaultVAO); if(defaultVAO)
if(scratchVAO) glDeleteVertexArrays(1, &scratchVAO); glDeleteVertexArrays(1, &defaultVAO);
if(scratchVAO)
glDeleteVertexArrays(1, &scratchVAO);
} }
#endif #endif

3
src/Magnum/GL/Implementation/State.cpp

@ -169,7 +169,8 @@ Containers::Pair<Containers::ArrayTuple, Containers::Reference<State>> State::al
Debug{out} << "Using optional features:"; Debug{out} << "Using optional features:";
for(const char* extension: extensions) for(const char* extension: extensions)
if(extension) Debug(out) << " " << extension; if(extension)
Debug(out) << " " << extension;
return {Utility::move(data), state}; return {Utility::move(data), state};
} }

21
src/Magnum/GL/Mesh.cpp

@ -347,7 +347,8 @@ Mesh::~Mesh() {
/* Remove current vao from the state */ /* Remove current vao from the state */
GLuint& current = Context::current().state().mesh.currentVAO; GLuint& current = Context::current().state().mesh.currentVAO;
if(current == _id) current = 0; if(current == _id)
current = 0;
Context::current().state().mesh.destroyImplementation(*this); Context::current().state().mesh.destroyImplementation(*this);
} }
@ -1103,7 +1104,8 @@ void Mesh::drawInternal(TransformFeedback& xfb, const UnsignedInt stream, const
/* Default stream */ /* Default stream */
if(stream == 0) { if(stream == 0) {
/* Non-instanced mesh */ /* Non-instanced mesh */
if(instanceCount == 1) glDrawTransformFeedback(GLenum(_primitive), xfb.id()); if(instanceCount == 1)
glDrawTransformFeedback(GLenum(_primitive), xfb.id());
/* Instanced mesh */ /* Instanced mesh */
else glDrawTransformFeedbackInstanced(GLenum(_primitive), xfb.id(), instanceCount); else glDrawTransformFeedbackInstanced(GLenum(_primitive), xfb.id(), instanceCount);
@ -1111,7 +1113,8 @@ void Mesh::drawInternal(TransformFeedback& xfb, const UnsignedInt stream, const
/* Specific stream */ /* Specific stream */
} else { } else {
/* Non-instanced mesh */ /* Non-instanced mesh */
if(instanceCount == 1) glDrawTransformFeedbackStream(GLenum(_primitive), xfb.id(), stream); if(instanceCount == 1)
glDrawTransformFeedbackStream(GLenum(_primitive), xfb.id(), stream);
/* Instanced mesh */ /* Instanced mesh */
else glDrawTransformFeedbackStreamInstanced(GLenum(_primitive), xfb.id(), stream, instanceCount); else glDrawTransformFeedbackStreamInstanced(GLenum(_primitive), xfb.id(), stream, instanceCount);
@ -1289,11 +1292,13 @@ void Mesh::attributePointerImplementationVAODSAIntelWindows(Mesh& self, Attribut
/* See the "angle-instanced-attributes-always-draw-instanced" workaround for /* See the "angle-instanced-attributes-always-draw-instanced" workaround for
these two */ these two */
void Mesh::attributePointerImplementationDefaultAngleAlwaysInstanced(Mesh& self, AttributeLayout&& attribute) { void Mesh::attributePointerImplementationDefaultAngleAlwaysInstanced(Mesh& self, AttributeLayout&& attribute) {
if(attribute.divisor) self._instanced = true; if(attribute.divisor)
self._instanced = true;
return attributePointerImplementationDefault(self, Utility::move(attribute)); return attributePointerImplementationDefault(self, Utility::move(attribute));
} }
void Mesh::attributePointerImplementationVAOAngleAlwaysInstanced(Mesh& self, AttributeLayout&& attribute) { void Mesh::attributePointerImplementationVAOAngleAlwaysInstanced(Mesh& self, AttributeLayout&& attribute) {
if(attribute.divisor) self._instanced = true; if(attribute.divisor)
self._instanced = true;
return attributePointerImplementationVAO(self, Utility::move(attribute)); return attributePointerImplementationVAO(self, Utility::move(attribute));
} }
#endif #endif
@ -1404,7 +1409,8 @@ void Mesh::bindImplementationDefault(Mesh& self) {
self.vertexAttribPointer(attribute); self.vertexAttribPointer(attribute);
/* Bind index buffer, if the mesh is indexed */ /* Bind index buffer, if the mesh is indexed */
if(self._indexBuffer.id()) self._indexBuffer.bindInternal(Buffer::TargetHint::ElementArray); if(self._indexBuffer.id())
self._indexBuffer.bindInternal(Buffer::TargetHint::ElementArray);
} }
void Mesh::bindImplementationVAO(Mesh& self) { void Mesh::bindImplementationVAO(Mesh& self) {
@ -1492,7 +1498,8 @@ void Mesh::multiDrawElementsBaseVertexImplementationANGLE(const GLenum mode, con
{NoInit, std::size_t(drawCount), instanceCount}, {NoInit, std::size_t(drawCount), instanceCount},
{ValueInit, std::size_t(drawCount), baseInstance}, {ValueInit, std::size_t(drawCount), baseInstance},
}; };
for(GLsizei& i: instanceCount) i = 1; for(GLsizei& i: instanceCount)
i = 1;
glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(mode, count, type, indices, instanceCount, baseVertex, baseInstance, drawCount); glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(mode, count, type, indices, instanceCount, baseVertex, baseInstance, drawCount);
} }

3
src/Magnum/GL/MeshView.cpp

@ -120,7 +120,8 @@ void MeshView::multiDrawImplementationDefault(const Containers::Iterable<MeshVie
counts[i] = meshes[i]._count; counts[i] = meshes[i]._count;
vertexOffsets[i] = meshes[i]._baseVertex; vertexOffsets[i] = meshes[i]._baseVertex;
indexOffsets[i] = original._indexBufferOffset + indexTypeSize*meshes[i]._indexOffset; indexOffsets[i] = original._indexBufferOffset + indexTypeSize*meshes[i]._indexOffset;
if(meshes[i]._baseVertex) useVertexOffsets = true; if(meshes[i]._baseVertex)
useVertexOffsets = true;
} }
original.drawInternal(counts, useVertexOffsets ? vertexOffsets : nullptr, indexOffsets); original.drawInternal(counts, useVertexOffsets ? vertexOffsets : nullptr, indexOffsets);

3
src/Magnum/GL/PrimitiveQuery.cpp

@ -47,7 +47,8 @@ void PrimitiveQuery::begin(const UnsignedInt index) {
void PrimitiveQuery::end() { void PrimitiveQuery::end() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!_index) glEndQuery(_target); if(!_index)
glEndQuery(_target);
else glEndQueryIndexed(_target, _index); else glEndQueryIndexed(_target, _index);
#else #else
AbstractQuery::end(); AbstractQuery::end();

3
src/Magnum/GL/Renderbuffer.cpp

@ -95,7 +95,8 @@ Renderbuffer::~Renderbuffer() {
/* If bound, remove itself from state */ /* If bound, remove itself from state */
GLuint& binding = Context::current().state().framebuffer.renderbufferBinding; GLuint& binding = Context::current().state().framebuffer.renderbufferBinding;
if(binding == _id) binding = 0; if(binding == _id)
binding = 0;
glDeleteRenderbuffers(1, &_id); glDeleteRenderbuffers(1, &_id);
} }

12
src/Magnum/GL/Shader.cpp

@ -858,7 +858,8 @@ void Shader::addSourceImplementationEmscriptenPthread(Shader& self, Containers::
description for details. */ description for details. */
if(!source.isSmall() && !source.deleter()) if(!source.isSmall() && !source.deleter())
source = Containers::String{source}; source = Containers::String{source};
for(char& c: source) if(c < 0) c = ' '; for(char& c: source) if(c < 0)
c = ' ';
arrayAppend(self._sources, Utility::move(source)); arrayAppend(self._sources, Utility::move(source));
} }
#endif #endif
@ -942,9 +943,11 @@ bool Shader::checkCompile() {
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
bool Shader::compile(std::initializer_list<Containers::Reference<Shader>> shaders) { bool Shader::compile(std::initializer_list<Containers::Reference<Shader>> shaders) {
/* Invoke (possibly parallel) compilation on all shaders */ /* Invoke (possibly parallel) compilation on all shaders */
for(Shader& shader: shaders) shader.submitCompile(); for(Shader& shader: shaders)
shader.submitCompile();
bool allSuccess = true; bool allSuccess = true;
for(Shader& shader: shaders) allSuccess = allSuccess && shader.checkCompile(); for(Shader& shader: shaders)
allSuccess = allSuccess && shader.checkCompile();
return allSuccess; return allSuccess;
} }
#endif #endif
@ -959,7 +962,8 @@ void Shader::cleanLogImplementationNoOp(Containers::String&) {}
#if defined(CORRADE_TARGET_WINDOWS) && !defined(MAGNUM_TARGET_GLES) #if defined(CORRADE_TARGET_WINDOWS) && !defined(MAGNUM_TARGET_GLES)
void Shader::cleanLogImplementationIntelWindows(Containers::String& message) { void Shader::cleanLogImplementationIntelWindows(Containers::String& message) {
if(message == "No errors.\n") message = {}; if(message == "No errors.\n")
message = {};
} }
#endif #endif

18
src/Magnum/GL/Test/CubeMapTextureGLTest.cpp

@ -1858,7 +1858,8 @@ void CubeMapTextureGLTest::compressedImage3D() {
"ARB_DSA compressed cubemap APIs are broken on AMD drivers."); "ARB_DSA compressed cubemap APIs are broken on AMD drivers.");
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
if(fails) CORRADE_SKIP("Skipping the rest of the test"); if(fails)
CORRADE_SKIP("Skipping the rest of the test");
} }
CompressedImage3D image = texture.compressedImage(0, {data.storage}); CompressedImage3D image = texture.compressedImage(0, {data.storage});
@ -1872,7 +1873,8 @@ void CubeMapTextureGLTest::compressedImage3D() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
#ifdef CORRADE_TARGET_WINDOWS #ifdef CORRADE_TARGET_WINDOWS
if(fails) CORRADE_SKIP("Skipping the rest of the test"); if(fails)
CORRADE_SKIP("Skipping the rest of the test");
#endif #endif
} }
@ -1911,7 +1913,8 @@ void CubeMapTextureGLTest::compressedImage3DBuffer() {
"ARB_DSA compressed cubemap APIs are broken on AMD drivers."); "ARB_DSA compressed cubemap APIs are broken on AMD drivers.");
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
if(fails) CORRADE_SKIP("Skipping the rest of the test"); if(fails)
CORRADE_SKIP("Skipping the rest of the test");
} }
CompressedBufferImage3D image = texture.compressedImage(0, {data.storage}, BufferUsage::StaticRead); CompressedBufferImage3D image = texture.compressedImage(0, {data.storage}, BufferUsage::StaticRead);
@ -1925,7 +1928,8 @@ void CubeMapTextureGLTest::compressedImage3DBuffer() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
#ifdef CORRADE_TARGET_WINDOWS #ifdef CORRADE_TARGET_WINDOWS
if(fails) CORRADE_SKIP("Skipping the rest of the test"); if(fails)
CORRADE_SKIP("Skipping the rest of the test");
#endif #endif
} }
@ -1963,7 +1967,8 @@ void CubeMapTextureGLTest::compressedImage3DQueryView() {
"ARB_DSA compressed cubemap APIs are broken on AMD drivers."); "ARB_DSA compressed cubemap APIs are broken on AMD drivers.");
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
if(fails) CORRADE_SKIP("Skipping the rest of the test"); if(fails)
CORRADE_SKIP("Skipping the rest of the test");
} }
Containers::Array<char> imageData{data.offset + 16*6}; Containers::Array<char> imageData{data.offset + 16*6};
@ -1979,7 +1984,8 @@ void CubeMapTextureGLTest::compressedImage3DQueryView() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
#ifdef CORRADE_TARGET_WINDOWS #ifdef CORRADE_TARGET_WINDOWS
if(fails) CORRADE_SKIP("Skipping the rest of the test"); if(fails)
CORRADE_SKIP("Skipping the rest of the test");
#endif #endif
} }

3
src/Magnum/GL/Test/MeshGLTest.cpp

@ -1444,7 +1444,8 @@ Checker::Checker(AbstractShaderProgram&& shader, RenderbufferFormat format, Mesh
#endif #endif
; ;
if(view.mesh().isIndexed()) view.setIndexOffset(1); if(view.mesh().isIndexed())
view.setIndexOffset(1);
shader.draw(view); shader.draw(view);
} }

3
src/Magnum/GL/TransformFeedback.cpp

@ -137,7 +137,8 @@ TransformFeedback::~TransformFeedback() {
/* If bound, remove itself from state */ /* If bound, remove itself from state */
GLuint& binding = Context::current().state().transformFeedback.binding; GLuint& binding = Context::current().state().transformFeedback.binding;
if(binding == _id) binding = 0; if(binding == _id)
binding = 0;
glDeleteTransformFeedbacks(1, &_id); glDeleteTransformFeedbacks(1, &_id);
} }

3
src/Magnum/Image.cpp

@ -115,7 +115,8 @@ template<UnsignedInt dimensions> CompressedImage<dimensions>::CompressedImage(co
size check below could then die on division by zero. Exit early in that size check below could then die on division by zero. Exit early in that
case. */ case. */
/** @todo any better idea to handle this? ugh */ /** @todo any better idea to handle this? ugh */
if(!passed) return; if(!passed)
return;
#else #else
static_cast<void>(passed); static_cast<void>(passed);
#endif #endif

6
src/Magnum/ImageView.cpp

@ -64,7 +64,8 @@ template<UnsignedInt dimensions, class T> void ImageView<dimensions, T>::setData
} }
template<UnsignedInt dimensions, class T> auto ImageView<dimensions, T>::pixels() const -> Containers::StridedArrayView<dimensions + 1, Type> { template<UnsignedInt dimensions, class T> auto ImageView<dimensions, T>::pixels() const -> Containers::StridedArrayView<dimensions + 1, Type> {
if(!_data && !_data.size()) return {}; if(!_data && !_data.size())
return {};
return Implementation::imagePixelView<dimensions, Type>(*this, data()); return Implementation::imagePixelView<dimensions, Type>(*this, data());
} }
@ -87,7 +88,8 @@ template<UnsignedInt dimensions, class T> CompressedImageView<dimensions, T>::Co
size check below could then die on division by zero. Exit early in that size check below could then die on division by zero. Exit early in that
case. */ case. */
/** @todo any better idea to handle this? ugh */ /** @todo any better idea to handle this? ugh */
if(!passed) return; if(!passed)
return;
#else #else
static_cast<void>(passed); static_cast<void>(passed);
#endif #endif

3
src/Magnum/ImageView.h

@ -532,7 +532,8 @@ template<UnsignedInt dimensions, class T> class ImageView {
* as well. See also @ref Image-pixel-access for more information. * as well. See also @ref Image-pixel-access for more information.
*/ */
template<class U> Containers::StridedArrayView<dimensions, typename std::conditional<std::is_const<Type>::value, typename std::add_const<U>::type, U>::type> pixels() const { template<class U> Containers::StridedArrayView<dimensions, typename std::conditional<std::is_const<Type>::value, typename std::add_const<U>::type, U>::type> pixels() const {
if(!_data && !_data.size()) return {}; if(!_data && !_data.size())
return {};
/* Deliberately not adding a StridedArrayView include, it should /* Deliberately not adding a StridedArrayView include, it should
work without since this is a templated function and we declare work without since this is a templated function and we declare
arrayCast() above to satisfy two-phase lookup. */ arrayCast() above to satisfy two-phase lookup. */

6
src/Magnum/MaterialTools/Filter.cpp

@ -80,7 +80,8 @@ Trade::MaterialData filterAttributesLayersImplementation(const Trade::MaterialDa
std::size_t layerCount; std::size_t layerCount;
if(inputLayersToKeep.data()) { if(inputLayersToKeep.data()) {
layerCount = inputLayersToKeep.count(); layerCount = inputLayersToKeep.count();
if(!inputLayersToKeep[0]) ++layerCount; if(!inputLayersToKeep[0])
++layerCount;
} else layerCount = material.layerCount(); } else layerCount = material.layerCount();
/* Fill in the layer offsets based on count of attributes in each, skipping /* Fill in the layer offsets based on count of attributes in each, skipping
@ -91,7 +92,8 @@ Trade::MaterialData filterAttributesLayersImplementation(const Trade::MaterialDa
for(UnsignedInt i = 0; i != material.layerCount(); ++i) { for(UnsignedInt i = 0; i != material.layerCount(); ++i) {
if(inputLayersToKeep.data() && !inputLayersToKeep[i]) { if(inputLayersToKeep.data() && !inputLayersToKeep[i]) {
/* The base layer stays, just gets empty */ /* The base layer stays, just gets empty */
if(i == 0) layers[layerOffset++] = 0; if(i == 0)
layers[layerOffset++] = 0;
continue; continue;
} }
layers[layerOffset++] = patchedInputAttributesToKeep.prefix(material.attributeDataOffset(i + 1)).count(); layers[layerOffset++] = patchedInputAttributesToKeep.prefix(material.attributeDataOffset(i + 1)).count();

6
src/Magnum/MaterialTools/PhongToPbrMetallicRoughness.cpp

@ -62,7 +62,8 @@ Containers::Optional<Trade::MaterialData> phongToPbrMetallicRoughness(const Trad
Trade::MaterialAttribute::Shininess Trade::MaterialAttribute::Shininess
}) { }) {
const Containers::Optional<UnsignedInt> id = material.findAttributeId(attribute); const Containers::Optional<UnsignedInt> id = material.findAttributeId(attribute);
if(!id) continue; if(!id)
continue;
if(flags >= PhongToPbrMetallicRoughnessFlag::FailOnUnconvertibleAttributes) { if(flags >= PhongToPbrMetallicRoughnessFlag::FailOnUnconvertibleAttributes) {
Error{} << "MaterialTools::phongToPbrMetallicRoughness(): unconvertible" << attribute << "attribute"; Error{} << "MaterialTools::phongToPbrMetallicRoughness(): unconvertible" << attribute << "attribute";
@ -78,7 +79,8 @@ Containers::Optional<Trade::MaterialData> phongToPbrMetallicRoughness(const Trad
Trade::MaterialAttribute::SpecularTexture Trade::MaterialAttribute::SpecularTexture
}) { }) {
const Containers::Optional<UnsignedInt> id = material.findAttributeId(attribute); const Containers::Optional<UnsignedInt> id = material.findAttributeId(attribute);
if(!id) continue; if(!id)
continue;
if(flags >= PhongToPbrMetallicRoughnessFlag::FailOnUnconvertibleAttributes) { if(flags >= PhongToPbrMetallicRoughnessFlag::FailOnUnconvertibleAttributes) {
Error{} << "MaterialTools::phongToPbrMetallicRoughness(): unconvertible" << attribute << "attribute"; Error{} << "MaterialTools::phongToPbrMetallicRoughness(): unconvertible" << attribute << "attribute";

3
src/Magnum/Math/Algorithms/KahanSum.h

@ -71,7 +71,8 @@ template<class Iterator, class T = typename std::decay<decltype(*std::declval<It
sum = t; sum = t;
} }
if(compensation) *compensation = c; if(compensation)
*compensation = c;
return sum; return sum;
} }

6
src/Magnum/Math/Algorithms/Svd.h

@ -143,7 +143,8 @@ template<std::size_t cols, std::size_t rows, class T> Containers::Optional<Conta
} else g = T(0); } else g = T(0);
const T y = std::abs(q[i]) + std::abs(e[i]); const T y = std::abs(q[i]) + std::abs(e[i]);
if(y > epsilonX) epsilonX = y; if(y > epsilonX)
epsilonX = y;
} }
/* Accumulation of right hand transformations */ /* Accumulation of right hand transformations */
@ -229,7 +230,8 @@ template<std::size_t cols, std::size_t rows, class T> Containers::Optional<Conta
const T f = s*e[i]; const T f = s*e[i];
e[i] = c*e[i]; e[i] = c*e[i];
if(std::abs(f) <= epsilon) break; if(std::abs(f) <= epsilon)
break;
const T j = q[i]; const T j = q[i];
const T h = Implementation::pythagoras(f, j); const T h = Implementation::pythagoras(f, j);

3
src/Magnum/Math/Bezier.h

@ -189,7 +189,8 @@ template<UnsignedInt order, UnsignedInt dimensions, class T> class Bezier {
*/ */
bool operator==(const Bezier<order, dimensions, T>& other) const { bool operator==(const Bezier<order, dimensions, T>& other) const {
for(std::size_t i = 0; i != order + 1; ++i) for(std::size_t i = 0; i != order + 1; ++i)
if(_data[i] != other._data[i]) return false; if(_data[i] != other._data[i])
return false;
return true; return true;
} }

9
src/Magnum/Math/BitVector.h

@ -387,7 +387,8 @@ template<std::size_t size> Debug& operator<<(Debug& debug, const BitVector<size>
template<std::size_t size> inline bool BitVector<size>::operator==(const BitVector<size>& other) const { template<std::size_t size> inline bool BitVector<size>::operator==(const BitVector<size>& other) const {
for(std::size_t i = 0; i != size/8; ++i) for(std::size_t i = 0; i != size/8; ++i)
if(_data[i] != other._data[i]) return false; if(_data[i] != other._data[i])
return false;
/* Check last segment */ /* Check last segment */
if(size%8 && (_data[DataSize-1] & LastSegmentMask) != (other._data[DataSize-1] & LastSegmentMask)) if(size%8 && (_data[DataSize-1] & LastSegmentMask) != (other._data[DataSize-1] & LastSegmentMask))
@ -399,7 +400,8 @@ template<std::size_t size> inline bool BitVector<size>::operator==(const BitVect
template<std::size_t size> inline bool BitVector<size>::all() const { template<std::size_t size> inline bool BitVector<size>::all() const {
/* Check all full segments */ /* Check all full segments */
for(std::size_t i = 0; i != size/8; ++i) for(std::size_t i = 0; i != size/8; ++i)
if(_data[i] != FullSegmentMask) return false; if(_data[i] != FullSegmentMask)
return false;
/* Check last segment */ /* Check last segment */
if(size%8 && (_data[DataSize-1] & LastSegmentMask) != LastSegmentMask) if(size%8 && (_data[DataSize-1] & LastSegmentMask) != LastSegmentMask)
@ -411,7 +413,8 @@ template<std::size_t size> inline bool BitVector<size>::all() const {
template<std::size_t size> inline bool BitVector<size>::none() const { template<std::size_t size> inline bool BitVector<size>::none() const {
/* Check all full segments */ /* Check all full segments */
for(std::size_t i = 0; i != size/8; ++i) for(std::size_t i = 0; i != size/8; ++i)
if(_data[i]) return false; if(_data[i])
return false;
/* Check last segment */ /* Check last segment */
if(size%8 && (_data[DataSize-1] & LastSegmentMask)) if(size%8 && (_data[DataSize-1] & LastSegmentMask))

3
src/Magnum/Math/Color.h

@ -51,7 +51,8 @@ namespace Implementation {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> Color3<T> fromHsv(ColorHsv<T> hsv) { template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> Color3<T> fromHsv(ColorHsv<T> hsv) {
/* Remove repeats */ /* Remove repeats */
hsv.hue -= floor(T(hsv.hue)/T(360))*Deg<T>(360); hsv.hue -= floor(T(hsv.hue)/T(360))*Deg<T>(360);
if(hsv.hue < Deg<T>(0)) hsv.hue += Deg<T>(360); if(hsv.hue < Deg<T>(0))
hsv.hue += Deg<T>(360);
int h = int(T(hsv.hue)/T(60)) % 6; int h = int(T(hsv.hue)/T(60)) % 6;
T f = T(hsv.hue)/T(60) - h; T f = T(hsv.hue)/T(60) - h;

3
src/Magnum/Math/Complex.h

@ -648,7 +648,8 @@ template<class T> inline Complex<T> slerp(const Complex<T>& normalizedA, const C
const T cosAngle = dot(normalizedA, normalizedB); const T cosAngle = dot(normalizedA, normalizedB);
/* Avoid division by zero */ /* Avoid division by zero */
if(std::abs(cosAngle) >= T(1)) return Complex<T>{normalizedA}; if(std::abs(cosAngle) >= T(1))
return Complex<T>{normalizedA};
/** @todo couldn't this be done somewhat simpler? */ /** @todo couldn't this be done somewhat simpler? */
const T a = std::acos(cosAngle); const T a = std::acos(cosAngle);

9
src/Magnum/Math/ConfigurationValue.h

@ -92,7 +92,8 @@ template<std::size_t size, class T> struct ConfigurationValue<Magnum::Math::Vect
std::string output; std::string output;
for(std::size_t i = 0; i != size; ++i) { for(std::size_t i = 0; i != size; ++i) {
if(!output.empty()) output += ' '; if(!output.empty())
output += ' ';
output += ConfigurationValue<T>::toString(value[i], flags); output += ConfigurationValue<T>::toString(value[i], flags);
} }
@ -164,7 +165,8 @@ template<std::size_t cols, std::size_t rows, class T> struct ConfigurationValue<
for(std::size_t row = 0; row != rows; ++row) { for(std::size_t row = 0; row != rows; ++row) {
for(std::size_t col = 0; col != cols; ++col) { for(std::size_t col = 0; col != cols; ++col) {
if(!output.empty()) output += ' '; if(!output.empty())
output += ' ';
output += ConfigurationValue<T>::toString(value[col][row], flags); output += ConfigurationValue<T>::toString(value[col][row], flags);
} }
} }
@ -349,7 +351,8 @@ template<Magnum::UnsignedInt order, Magnum::UnsignedInt dimensions, class T> str
for(std::size_t o = 0; o != order + 1; ++o) { for(std::size_t o = 0; o != order + 1; ++o) {
for(std::size_t i = 0; i != dimensions; ++i) { for(std::size_t i = 0; i != dimensions; ++i) {
if(!output.empty()) output += ' '; if(!output.empty())
output += ' ';
output += ConfigurationValue<T>::toString(value[o][i], flags); output += ConfigurationValue<T>::toString(value[o][i], flags);
} }
} }

9
src/Magnum/Math/Frustum.h

@ -135,7 +135,8 @@ template<class T> class Frustum {
*/ */
bool operator==(const Frustum<T>& other) const { bool operator==(const Frustum<T>& other) const {
for(std::size_t i = 0; i != 6; ++i) for(std::size_t i = 0; i != 6; ++i)
if(_data[i] != other._data[i]) return false; if(_data[i] != other._data[i])
return false;
return true; return true;
} }
@ -292,9 +293,11 @@ template<class T> class Frustum {
template<class T> Debug& operator<<(Debug& debug, const Frustum<T>& value) { template<class T> Debug& operator<<(Debug& debug, const Frustum<T>& value) {
debug << "Frustum({" << Debug::nospace; debug << "Frustum({" << Debug::nospace;
for(std::size_t i = 0; i != 6; ++i) { for(std::size_t i = 0; i != 6; ++i) {
if(i != 0) debug << Debug::nospace << "},\n {" << Debug::nospace; if(i != 0)
debug << Debug::nospace << "},\n {" << Debug::nospace;
for(std::size_t j = 0; j != 4; ++j) { for(std::size_t j = 0; j != 4; ++j) {
if(j != 0) debug << Debug::nospace << ","; if(j != 0)
debug << Debug::nospace << ",";
debug << value[i][j]; debug << value[i][j];
} }
} }

6
src/Magnum/Math/Functions.cpp

@ -75,9 +75,11 @@ UnsignedLong binomialCoefficient(const UnsignedInt n, UnsignedInt k) {
/* k and n - k gives the same value, optimize the calculation to do fewer /* k and n - k gives the same value, optimize the calculation to do fewer
steps */ steps */
if(k*2 > n) k = n - k; if(k*2 > n)
k = n - k;
if(k == 0) return 1; if(k == 0)
return 1;
UnsignedLong result = n; UnsignedLong result = n;
for(UnsignedInt i = 2; i <= k; ++i) { for(UnsignedInt i = 2; i <= k; ++i) {

21
src/Magnum/Math/Functions.h

@ -266,8 +266,8 @@ template<class T
*/ */
template<std::size_t size, class T> inline BitVector<size> isInf(const Vector<size, T>& value) { template<std::size_t size, class T> inline BitVector<size> isInf(const Vector<size, T>& value) {
BitVector<size> out; BitVector<size> out;
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i) if(Math::isInf(value[i]))
if(Math::isInf(value[i])) out.set(i); out.set(i);
return out; return out;
} }
@ -292,8 +292,8 @@ template<class T
*/ */
template<std::size_t size, class T> inline BitVector<size> isNan(const Vector<size, T>& value) { template<std::size_t size, class T> inline BitVector<size> isNan(const Vector<size, T>& value) {
BitVector<size> out; BitVector<size> out;
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i) if(Math::isNan(value[i]))
if(Math::isNan(value[i])) out.set(i); out.set(i);
return out; return out;
} }
@ -379,8 +379,8 @@ template<class T
template<std::size_t size, class T> inline Containers::Pair<Vector<size, T>, Vector<size, T>> minmax(const Vector<size, T>& a, const Vector<size, T>& b) { template<std::size_t size, class T> inline Containers::Pair<Vector<size, T>, Vector<size, T>> minmax(const Vector<size, T>& a, const Vector<size, T>& b) {
using Utility::swap; using Utility::swap;
Containers::Pair<Vector<size, T>, Vector<size, T>> out{a, b}; Containers::Pair<Vector<size, T>, Vector<size, T>> out{a, b};
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i) if(out.first()[i] > out.second()[i])
if(out.first()[i] > out.second()[i]) swap(out.first()[i], out.second()[i]); swap(out.first()[i], out.second()[i]);
return out; return out;
} }
@ -428,8 +428,10 @@ template<class T
, typename std::enable_if<IsScalar<T>::value, int>::type = 0 , typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif #endif
> inline UnderlyingTypeOf<T> sign(T scalar) { > inline UnderlyingTypeOf<T> sign(T scalar) {
if(scalar > T(0)) return UnderlyingTypeOf<T>(1); if(scalar > T(0))
if(scalar < T(0)) return UnderlyingTypeOf<T>(-1); return UnderlyingTypeOf<T>(1);
if(scalar < T(0))
return UnderlyingTypeOf<T>(-1);
return UnderlyingTypeOf<T>(0); return UnderlyingTypeOf<T>(0);
} }
@ -914,7 +916,8 @@ template<std::size_t size, class T> inline Vector<size, T> refract(const Vector<
"Math::refract(): vectors" << vector << "and" << normal << "are not normalized", {}); "Math::refract(): vectors" << vector << "and" << normal << "are not normalized", {});
const T dot = Math::dot(vector, normal); const T dot = Math::dot(vector, normal);
const T k = T(1.0) - eta*eta*(T(1.0) - dot*dot); const T k = T(1.0) - eta*eta*(T(1.0) - dot*dot);
if(k < T(0.0)) return {}; if(k < T(0.0))
return {};
return eta*vector - (eta*dot + std::sqrt(k))*normal; return eta*vector - (eta*dot + std::sqrt(k))*normal;
} }

31
src/Magnum/Math/FunctionsBatch.h

@ -72,14 +72,16 @@ empty, returns @cpp false @ce or a @ref BitVector with no bits set.
@see @ref isInf(T), @ref Constants::inf() @see @ref isInf(T), @ref Constants::inf()
*/ */
template<class T> auto isInf(const Containers::StridedArrayView1D<const T>& range) -> decltype(isInf(std::declval<T>())) { template<class T> auto isInf(const Containers::StridedArrayView1D<const T>& range) -> decltype(isInf(std::declval<T>())) {
if(range.isEmpty()) return {}; if(range.isEmpty())
return {};
/* For scalars, this loop exits once any value is infinity. For vectors /* For scalars, this loop exits once any value is infinity. For vectors
the loop accumulates the bits and exits as soon as all bits are set the loop accumulates the bits and exits as soon as all bits are set
or the input is exhausted */ or the input is exhausted */
auto out = isInf(range[0]); /* bool or BitVector */ auto out = isInf(range[0]); /* bool or BitVector */
for(std::size_t i = 1; i != range.size(); ++i) { for(std::size_t i = 1; i != range.size(); ++i) {
if(out) break; if(out)
break;
out = out || isInf(range[i]); out = out || isInf(range[i]);
} }
@ -124,14 +126,16 @@ returns @cpp false @ce or a @ref BitVector with no bits set.
@see @ref isNan(T), @ref Constants::nan() @see @ref isNan(T), @ref Constants::nan()
*/ */
template<class T> inline auto isNan(const Containers::StridedArrayView1D<const T>& range) -> decltype(isNan(std::declval<T>())) { template<class T> inline auto isNan(const Containers::StridedArrayView1D<const T>& range) -> decltype(isNan(std::declval<T>())) {
if(range.isEmpty()) return {}; if(range.isEmpty())
return {};
/* For scalars, this loop exits once any value is infinity. For vectors /* For scalars, this loop exits once any value is infinity. For vectors
the loop accumulates the bits and exits as soon as all bits are set the loop accumulates the bits and exits as soon as all bits are set
or the input is exhausted */ or the input is exhausted */
auto out = isNan(range[0]); /* bool or BitVector */ auto out = isNan(range[0]); /* bool or BitVector */
for(std::size_t i = 1; i != range.size(); ++i) { for(std::size_t i = 1; i != range.size(); ++i) {
if(out) break; if(out)
break;
out = out || isNan(range[i]); out = out || isNan(range[i]);
} }
@ -177,8 +181,8 @@ namespace Implementation {
/* Find the first non-NaN value to compare against. If all are NaN, /* Find the first non-NaN value to compare against. If all are NaN,
return the last value so the following loop in min/max/minmax() return the last value so the following loop in min/max/minmax()
doesn't even execute. */ doesn't even execute. */
for(std::size_t i = 0; i != range.size(); ++i) for(std::size_t i = 0; i != range.size(); ++i) if(!isNan(range[i]))
if(!isNan(range[i])) return {i, range[i]}; return {i, range[i]};
return {range.size() - 1, range.back()}; return {range.size() - 1, range.back()};
} }
/* Floating-point vectors. Try to gather non-NaN values for each component /* Floating-point vectors. Try to gather non-NaN values for each component
@ -193,8 +197,10 @@ namespace Implementation {
std::size_t firstValid = 0; std::size_t firstValid = 0;
for(std::size_t i = 1; i != range.size(); ++i) { for(std::size_t i = 1; i != range.size(); ++i) {
BitVector<T::Size> nans = isNan(out); BitVector<T::Size> nans = isNan(out);
if(nans.none()) break; if(nans.none())
if(nans.all() && firstValid + 1 == i) ++firstValid; break;
if(nans.all() && firstValid + 1 == i)
++firstValid;
out = Math::lerp(out, range[i], isNan(out)); out = Math::lerp(out, range[i], isNan(out));
} }
return {firstValid, out}; return {firstValid, out};
@ -209,7 +215,8 @@ ignored, unless the range is all <em>NaN</em>s.
@see @ref min(T, T), @ref isNan(const Containers::StridedArrayView1D<const T>&) @see @ref min(T, T), @ref isNan(const Containers::StridedArrayView1D<const T>&)
*/ */
template<class T> inline T min(const Containers::StridedArrayView1D<const T>& range) { template<class T> inline T min(const Containers::StridedArrayView1D<const T>& range) {
if(range.isEmpty()) return {}; if(range.isEmpty())
return {};
Containers::Pair<std::size_t, T> iOut = Implementation::firstNonNan(range, IsFloatingPoint<T>{}, IsVector<T>{}); Containers::Pair<std::size_t, T> iOut = Implementation::firstNonNan(range, IsFloatingPoint<T>{}, IsVector<T>{});
for(++iOut.first(); iOut.first() != range.size(); ++iOut.first()) for(++iOut.first(); iOut.first() != range.size(); ++iOut.first())
@ -254,7 +261,8 @@ ignored, unless the range is all <em>NaN</em>s.
@see @ref max(T, T), @ref isNan(const Containers::StridedArrayView1D<const T>&) @see @ref max(T, T), @ref isNan(const Containers::StridedArrayView1D<const T>&)
*/ */
template<class T> inline T max(const Containers::StridedArrayView1D<const T>& range) { template<class T> inline T max(const Containers::StridedArrayView1D<const T>& range) {
if(range.isEmpty()) return {}; if(range.isEmpty())
return {};
Containers::Pair<std::size_t, T> iOut = Implementation::firstNonNan(range, IsFloatingPoint<T>{}, IsVector<T>{}); Containers::Pair<std::size_t, T> iOut = Implementation::firstNonNan(range, IsFloatingPoint<T>{}, IsVector<T>{});
for(++iOut.first(); iOut.first() != range.size(); ++iOut.first()) for(++iOut.first(); iOut.first() != range.size(); ++iOut.first())
@ -314,7 +322,8 @@ ignored, unless the range is all <em>NaN</em>s.
@ref isNan(const Containers::StridedArrayView1D<const T>&) @ref isNan(const Containers::StridedArrayView1D<const T>&)
*/ */
template<class T> inline Containers::Pair<T, T> minmax(const Containers::StridedArrayView1D<const T>& range) { template<class T> inline Containers::Pair<T, T> minmax(const Containers::StridedArrayView1D<const T>& range) {
if(range.isEmpty()) return {}; if(range.isEmpty())
return {};
Containers::Pair<std::size_t, T> iOut = Implementation::firstNonNan(range, IsFloatingPoint<T>{}, IsVector<T>{}); Containers::Pair<std::size_t, T> iOut = Implementation::firstNonNan(range, IsFloatingPoint<T>{}, IsVector<T>{});
T min{iOut.second()}, max{iOut.second()}; T min{iOut.second()}, max{iOut.second()};

6
src/Magnum/Math/Intersection.h

@ -505,7 +505,8 @@ template<class T> bool rangeFrustum(const Range3D<T>& range, const Frustum<T>& f
const Float d = Math::dot(center, plane.xyz()); const Float d = Math::dot(center, plane.xyz());
const Float r = Math::dot(extent, absPlaneNormal); const Float r = Math::dot(extent, absPlaneNormal);
if(d + r < -T(2)*plane.w()) return false; if(d + r < -T(2)*plane.w())
return false;
} }
return true; return true;
@ -525,7 +526,8 @@ template<class T> bool aabbFrustum(const Vector3<T>& aabbCenter, const Vector3<T
const Float d = Math::dot(aabbCenter, plane.xyz()); const Float d = Math::dot(aabbCenter, plane.xyz());
const Float r = Math::dot(aabbExtents, absPlaneNormal); const Float r = Math::dot(aabbExtents, absPlaneNormal);
if(d + r < -plane.w()) return false; if(d + r < -plane.w())
return false;
} }
return true; return true;

3
src/Magnum/Math/Matrix.h

@ -474,7 +474,8 @@ template<std::size_t size, class T> bool Matrix<size, T>::isOrthogonal() const {
/* Normality */ /* Normality */
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
if(!RectangularMatrix<size, size, T>::_data[i].isNormalized()) return false; if(!RectangularMatrix<size, size, T>::_data[i].isNormalized())
return false;
/* Orthogonality */ /* Orthogonality */
for(std::size_t i = 0; i != size-1; ++i) for(std::size_t i = 0; i != size-1; ++i)

6
src/Magnum/Math/Quaternion.h

@ -888,8 +888,10 @@ template<class T> Quaternion<T> quaternionFromMatrix(const Matrix3x3<T>& m) {
/* Diagonal is negative */ /* Diagonal is negative */
std::size_t i = 0; std::size_t i = 0;
if(diagonal[1] > diagonal[0]) i = 1; if(diagonal[1] > diagonal[0])
if(diagonal[2] > diagonal[i]) i = 2; i = 1;
if(diagonal[2] > diagonal[i])
i = 2;
const std::size_t j = (i + 1) % 3; const std::size_t j = (i + 1) % 3;
const std::size_t k = (i + 2) % 3; const std::size_t k = (i + 2) % 3;

9
src/Magnum/Math/Range.h

@ -803,8 +803,10 @@ size.
@see @ref join(const Range<dimensions, T>&, const Vector<dimensions, T>&) @see @ref join(const Range<dimensions, T>&, const Vector<dimensions, T>&)
*/ */
template<UnsignedInt dimensions, class T> inline Range<dimensions, T> join(const Range<dimensions, T>& a, const Range<dimensions, T>& b) { template<UnsignedInt dimensions, class T> inline Range<dimensions, T> join(const Range<dimensions, T>& a, const Range<dimensions, T>& b) {
if(a.min() == a.max()) return b; if(a.min() == a.max())
if(b.min() == b.max()) return a; return b;
if(b.min() == b.max())
return a;
return {min(a.min(), b.min()), max(a.max(), b.max())}; return {min(a.min(), b.min()), max(a.max(), b.max())};
} }
@ -841,7 +843,8 @@ undefined if any range has a negative size.
@see @ref intersects() @see @ref intersects()
*/ */
template<UnsignedInt dimensions, class T> inline Range<dimensions, T> intersect(const Range<dimensions, T>& a, const Range<dimensions, T>& b) { template<UnsignedInt dimensions, class T> inline Range<dimensions, T> intersect(const Range<dimensions, T>& a, const Range<dimensions, T>& b) {
if(!intersects(a, b)) return {}; if(!intersects(a, b))
return {};
return {max(a.min(), b.min()), min(a.max(), b.max())}; return {max(a.min(), b.min()), min(a.max(), b.max())};
} }

9
src/Magnum/Math/RectangularMatrix.h

@ -316,7 +316,8 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
*/ */
bool operator==(const RectangularMatrix<cols, rows, T>& other) const { bool operator==(const RectangularMatrix<cols, rows, T>& other) const {
for(std::size_t i = 0; i != cols; ++i) for(std::size_t i = 0; i != cols; ++i)
if(_data[i] != other._data[i]) return false; if(_data[i] != other._data[i])
return false;
return true; return true;
} }
@ -775,9 +776,11 @@ template<std::size_t cols, std::size_t rows, class T> Debug& operator<<(Debug& d
const bool packed = debug.immediateFlags() >= Debug::Flag::Packed; const bool packed = debug.immediateFlags() >= Debug::Flag::Packed;
debug << (packed ? "{" : "Matrix(") << Debug::nospace; debug << (packed ? "{" : "Matrix(") << Debug::nospace;
for(std::size_t row = 0; row != rows; ++row) { for(std::size_t row = 0; row != rows; ++row) {
if(row != 0) debug << Debug::nospace << (packed ? ",\n" : ",\n "); if(row != 0)
debug << Debug::nospace << (packed ? ",\n" : ",\n ");
for(std::size_t col = 0; col != cols; ++col) { for(std::size_t col = 0; col != cols; ++col) {
if(col != 0) debug << Debug::nospace << ","; if(col != 0)
debug << Debug::nospace << ",";
debug << value[col][row]; debug << value[col][row];
} }
} }

3
src/Magnum/Math/Test/IntersectionBenchmark.cpp

@ -47,7 +47,8 @@ template<class T> bool rangeFrustumNaive(const Math::Range3D<T>& box, const Math
} }
/* All corners are outside this plane */ /* All corners are outside this plane */
if(!cornerHit) return false; if(!cornerHit)
return false;
} }
return true; return true;

6
src/Magnum/Math/TypeTraits.h

@ -529,7 +529,8 @@ template<class T> struct TypeTraitsFloatingPoint: TypeTraitsName<T> {
template<class T> bool TypeTraitsFloatingPoint<T>::equals(const T a, const T b) { template<class T> bool TypeTraitsFloatingPoint<T>::equals(const T a, const T b) {
/* Shortcut for binary equality (also infinites) */ /* Shortcut for binary equality (also infinites) */
if(a == b) return true; if(a == b)
return true;
const T absA = std::abs(a); const T absA = std::abs(a);
const T absB = std::abs(b); const T absB = std::abs(b);
@ -546,7 +547,8 @@ template<class T> bool TypeTraitsFloatingPoint<T>::equals(const T a, const T b)
template<class T> bool TypeTraitsFloatingPoint<T>::equalsZero(const T a, const T magnitude) { template<class T> bool TypeTraitsFloatingPoint<T>::equalsZero(const T a, const T magnitude) {
/* Shortcut for binary equality */ /* Shortcut for binary equality */
if(a == T(0.0)) return true; if(a == T(0.0))
return true;
const T absA = std::abs(a); const T absA = std::abs(a);

10
src/Magnum/Math/Vector.h

@ -300,7 +300,8 @@ template<std::size_t size, class T> class Vector {
*/ */
bool operator==(const Vector<size, T>& other) const { bool operator==(const Vector<size, T>& other) const {
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
if(!TypeTraits<T>::equals(_data[i], other._data[i])) return false; if(!TypeTraits<T>::equals(_data[i], other._data[i]))
return false;
return true; return true;
} }
@ -1301,7 +1302,8 @@ template<std::size_t size, class T> Debug& operator<<(Debug& debug, const Vector
const bool packed = debug.immediateFlags() >= Debug::Flag::Packed; const bool packed = debug.immediateFlags() >= Debug::Flag::Packed;
debug << (packed ? "{" : "Vector(") << Debug::nospace; debug << (packed ? "{" : "Vector(") << Debug::nospace;
for(std::size_t i = 0; i != size; ++i) { for(std::size_t i = 0; i != size; ++i) {
if(i != 0) debug << Debug::nospace << ","; if(i != 0)
debug << Debug::nospace << ",";
debug << value[i]; debug << value[i];
} }
debug << Debug::nospace << (packed ? "}" : ")"); debug << Debug::nospace << (packed ? "}" : ")");
@ -1599,8 +1601,8 @@ namespace Implementation {
/* Find the first non-NaN value to compare against. If all are NaN, /* Find the first non-NaN value to compare against. If all are NaN,
return the last value so the following loop in min/max/minmax() return the last value so the following loop in min/max/minmax()
doesn't even execute. */ doesn't even execute. */
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i) if(!isNan(data[i]))
if(!isNan(data[i])) return i; return i;
return size - 1; return size - 1;
} }
} }

6
src/Magnum/Mesh.cpp

@ -113,7 +113,8 @@ Containers::String ConfigurationValue<Magnum::MeshPrimitive>::toString(Magnum::M
Magnum::MeshPrimitive ConfigurationValue<Magnum::MeshPrimitive>::fromString(Containers::StringView stringValue, ConfigurationValueFlags) { Magnum::MeshPrimitive ConfigurationValue<Magnum::MeshPrimitive>::fromString(Containers::StringView stringValue, ConfigurationValueFlags) {
for(std::size_t i = 0; i != Containers::arraySize(Magnum::MeshPrimitiveNames); ++i) for(std::size_t i = 0; i != Containers::arraySize(Magnum::MeshPrimitiveNames); ++i)
if(stringValue == Magnum::MeshPrimitiveNames[i]) return Magnum::MeshPrimitive(i + 1); if(stringValue == Magnum::MeshPrimitiveNames[i])
return Magnum::MeshPrimitive(i + 1);
return {}; return {};
} }
@ -127,7 +128,8 @@ Containers::String ConfigurationValue<Magnum::MeshIndexType>::toString(Magnum::M
Magnum::MeshIndexType ConfigurationValue<Magnum::MeshIndexType>::fromString(Containers::StringView stringValue, ConfigurationValueFlags) { Magnum::MeshIndexType ConfigurationValue<Magnum::MeshIndexType>::fromString(Containers::StringView stringValue, ConfigurationValueFlags) {
for(std::size_t i = 0; i != Containers::arraySize(Magnum::MeshIndexTypeNames); ++i) for(std::size_t i = 0; i != Containers::arraySize(Magnum::MeshIndexTypeNames); ++i)
if(stringValue == Magnum::MeshIndexTypeNames[i]) return Magnum::MeshIndexType(i + 1); if(stringValue == Magnum::MeshIndexTypeNames[i])
return Magnum::MeshIndexType(i + 1);
return {}; return {};
} }

3
src/Magnum/MeshTools/BoundingVolume.cpp

@ -42,7 +42,8 @@ Range3D boundingRange(const Containers::StridedArrayView1D<const Vector3>& point
Containers::Pair<Vector3, Float> boundingSphereBouncingBubble(const Containers::StridedArrayView1D<const Vector3>& points) { Containers::Pair<Vector3, Float> boundingSphereBouncingBubble(const Containers::StridedArrayView1D<const Vector3>& points) {
/* See comment about radius below, this is done for consistency */ /* See comment about radius below, this is done for consistency */
if(points.isEmpty()) return {{}, Math::TypeTraits<Float>::epsilon()}; if(points.isEmpty())
return {{}, Math::TypeTraits<Float>::epsilon()};
/** @todo Skip NaNs here? To match behaviour of boundingBoxAxisAligned() /** @todo Skip NaNs here? To match behaviour of boundingBoxAxisAligned()
which uses minmax(). */ which uses minmax(). */

9
src/Magnum/MeshTools/Compile.cpp

@ -495,9 +495,12 @@ GL::Mesh compile(const Trade::MeshData3D& meshData, CompileFlags flags) {
} else { } else {
positions = meshData.positions(0); positions = meshData.positions(0);
if(meshData.hasNormals()) normals = meshData.normals(0); if(meshData.hasNormals())
if(meshData.hasTextureCoords2D()) textureCoords2D = meshData.textureCoords2D(0); normals = meshData.normals(0);
if(meshData.hasColors()) colors = meshData.colors(0); if(meshData.hasTextureCoords2D())
textureCoords2D = meshData.textureCoords2D(0);
if(meshData.hasColors())
colors = meshData.colors(0);
useIndices = meshData.isIndexed(); useIndices = meshData.isIndexed();
} }

9
src/Magnum/MeshTools/Concatenate.cpp

@ -44,12 +44,14 @@ Containers::Pair<UnsignedInt, UnsignedInt> concatenateIndexVertexCount(const Con
indexed mesh, all previous meshes will have a trivial index buffer indexed mesh, all previous meshes will have a trivial index buffer
generated for all their vertices */ generated for all their vertices */
if(mesh.isIndexed()) { if(mesh.isIndexed()) {
if(!indexCount) indexCount = vertexCount; if(!indexCount)
indexCount = vertexCount;
indexCount += mesh.indexCount(); indexCount += mesh.indexCount();
/* Otherwise, if some earlier mesh was indexed, this mesh will have a /* Otherwise, if some earlier mesh was indexed, this mesh will have a
trivial index buffer generated for all its vertices */ trivial index buffer generated for all its vertices */
} else if(indexCount) indexCount += mesh.vertexCount(); } else if(indexCount)
indexCount += mesh.vertexCount();
vertexCount += mesh.vertexCount(); vertexCount += mesh.vertexCount();
} }
@ -111,7 +113,8 @@ Trade::MeshData concatenate(Containers::Array<char>&& indexData, const UnsignedI
indexOffset += mesh.indexCount(); indexOffset += mesh.indexCount();
/* Adjust indices for current vertex offset */ /* Adjust indices for current vertex offset */
for(UnsignedInt& index: dst) index += vertexOffset; for(UnsignedInt& index: dst)
index += vertexOffset;
/* Otherwise, if we need an index buffer (meaning at least one of the /* Otherwise, if we need an index buffer (meaning at least one of the
meshes is indexed), generate a trivial index buffer */ meshes is indexed), generate a trivial index buffer */

3
src/Magnum/MeshTools/Duplicate.cpp

@ -112,7 +112,8 @@ Trade::MeshData duplicate(const Trade::MeshData& mesh, const Containers::ArrayVi
UnsignedInt attributeIndex = mesh.attributeCount(); UnsignedInt attributeIndex = mesh.attributeCount();
for(UnsignedInt i = 0; i != extra.size(); ++i) { for(UnsignedInt i = 0; i != extra.size(); ++i) {
/* Padding, ignore */ /* Padding, ignore */
if(extra[i].format() == VertexFormat{}) continue; if(extra[i].format() == VertexFormat{})
continue;
/* Asserting here even though data() has another assert since that one /* Asserting here even though data() has another assert since that one
would be too confusing in this context */ would be too confusing in this context */

15
src/Magnum/MeshTools/GenerateNormals.cpp

@ -69,14 +69,16 @@ template<class T> inline void generateSmoothNormalsIntoImplementation(const Cont
CORRADE_ASSERT(normals.size() == positions.size(), CORRADE_ASSERT(normals.size() == positions.size(),
"MeshTools::generateSmoothNormalsInto(): bad output size, expected" << positions.size() << "but got" << normals.size(), ); "MeshTools::generateSmoothNormalsInto(): bad output size, expected" << positions.size() << "but got" << normals.size(), );
if(indices.isEmpty()) return; if(indices.isEmpty())
return;
/* Gather count of triangles for every vertex. This abuses the output /* Gather count of triangles for every vertex. This abuses the output
storage to avoid extra allocations, zero-initialize it first to avoid storage to avoid extra allocations, zero-initialize it first to avoid
random memory getting used. */ random memory getting used. */
Containers::StridedArrayView1D<UnsignedInt> triangleCount = Containers::StridedArrayView1D<UnsignedInt> triangleCount =
Containers::arrayCast<UnsignedInt>(normals); Containers::arrayCast<UnsignedInt>(normals);
for(UnsignedInt& i: triangleCount) i = 0; for(UnsignedInt& i: triangleCount)
i = 0;
for(const T index: indices) { for(const T index: indices) {
CORRADE_ASSERT(index < positions.size(), "MeshTools::generateSmoothNormalsInto(): index" << index << "out of range for" << positions.size() << "elements", ); CORRADE_ASSERT(index < positions.size(), "MeshTools::generateSmoothNormalsInto(): index" << index << "out of range for" << positions.size() << "elements", );
++triangleCount[index]; ++triangleCount[index];
@ -168,9 +170,12 @@ template<class T> inline void generateSmoothNormalsIntoImplementation(const Cont
/* Angle between two sides of the triangle that share vertex `v`. /* Angle between two sides of the triangle that share vertex `v`.
The shared vertex can be one of the three. */ The shared vertex can be one of the three. */
Rad angle; Rad angle;
if(v == v0i) angle = crossAngle.second()[0]; if(v == v0i)
else if(v == v1i) angle = crossAngle.second()[1]; angle = crossAngle.second()[0];
else if(v == v2i) angle = crossAngle.second()[2]; else if(v == v1i)
angle = crossAngle.second()[1];
else if(v == v2i)
angle = crossAngle.second()[2];
else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
/* The normal is cross.normalized(), we need to multiply it it by /* The normal is cross.normalized(), we need to multiply it it by

15
src/Magnum/MeshTools/Interleave.cpp

@ -62,7 +62,8 @@ Containers::Optional<Containers::StridedArrayView2D<const char>> interleavedData
std::size_t maxOffset = 0; std::size_t maxOffset = 0;
bool hasImplementationSpecificVertexFormat = false; bool hasImplementationSpecificVertexFormat = false;
for(UnsignedInt i = 0; i != mesh.attributeCount(); ++i) { for(UnsignedInt i = 0; i != mesh.attributeCount(); ++i) {
if(mesh.attributeStride(i) != stride) return Containers::NullOpt; if(mesh.attributeStride(i) != stride)
return Containers::NullOpt;
const std::size_t offset = mesh.attributeOffset(i); const std::size_t offset = mesh.attributeOffset(i);
minOffset = Math::min(minOffset, offset); minOffset = Math::min(minOffset, offset);
@ -139,7 +140,8 @@ namespace Implementation {
Containers::Array<Trade::MeshAttributeData> interleavedLayout(Trade::MeshData&& mesh, const Containers::ArrayView<const Trade::MeshAttributeData> extra, const InterleaveFlags flags) { Containers::Array<Trade::MeshAttributeData> interleavedLayout(Trade::MeshData&& mesh, const Containers::ArrayView<const Trade::MeshAttributeData> extra, const InterleaveFlags flags) {
/* Nothing to do here, bye! */ /* Nothing to do here, bye! */
if(!mesh.attributeCount() && extra.isEmpty()) return {}; if(!mesh.attributeCount() && extra.isEmpty())
return {};
/* If we're not told to preserve the layout, treat the mesh as /* If we're not told to preserve the layout, treat the mesh as
noninterleaved always, forcing a repack. Otherwise check if it's already noninterleaved always, forcing a repack. Otherwise check if it's already
@ -204,14 +206,16 @@ Containers::Array<Trade::MeshAttributeData> interleavedLayout(Trade::MeshData&&
preserve relative attribute offsets, otherwise pack tightly. */ preserve relative attribute offsets, otherwise pack tightly. */
std::size_t offset = 0; std::size_t offset = 0;
for(UnsignedInt i = 0; i != originalAttributeCount; ++i) { for(UnsignedInt i = 0; i != originalAttributeCount; ++i) {
if(interleaved) offset = attributeData[i].offset(mesh.vertexData()) - minOffset; if(interleaved)
offset = attributeData[i].offset(mesh.vertexData()) - minOffset;
attributeData[i] = Trade::MeshAttributeData{ attributeData[i] = Trade::MeshAttributeData{
attributeData[i].name(), attributeData[i].format(), attributeData[i].name(), attributeData[i].format(),
offset, 0, std::ptrdiff_t(stride), offset, 0, std::ptrdiff_t(stride),
attributeData[i].arraySize(), attributeData[i].morphTargetId()}; attributeData[i].arraySize(), attributeData[i].morphTargetId()};
if(!interleaved) offset += attributeSize(attributeData[i]); if(!interleaved)
offset += attributeSize(attributeData[i]);
} }
/* In case the original is already interleaved, set the offset for extra /* In case the original is already interleaved, set the offset for extra
@ -361,7 +365,8 @@ Trade::MeshData interleave(Trade::MeshData&& mesh, const Containers::ArrayView<c
UnsignedInt attributeIndex = mesh.attributeCount(); UnsignedInt attributeIndex = mesh.attributeCount();
for(UnsignedInt i = 0; i != extra.size(); ++i) { for(UnsignedInt i = 0; i != extra.size(); ++i) {
/* Padding, ignore */ /* Padding, ignore */
if(extra[i].format() == VertexFormat{}) continue; if(extra[i].format() == VertexFormat{})
continue;
/* Asserting here even though data() has another assert since that /* Asserting here even though data() has another assert since that
one would be too confusing in this context */ one would be too confusing in this context */

12
src/Magnum/MeshTools/RemoveDuplicates.cpp

@ -177,7 +177,8 @@ template<class IndexType> std::size_t removeDuplicatesIndexedInPlaceImplementati
inverted (having the *Indexed() variant as the main implementation) inverted (having the *Indexed() variant as the main implementation)
because the remapping there has to be done once for every dimension. */ because the remapping there has to be done once for every dimension. */
const Containers::Pair<Containers::Array<UnsignedInt>, std::size_t> result = removeDuplicatesInPlace(data); const Containers::Pair<Containers::Array<UnsignedInt>, std::size_t> result = removeDuplicatesInPlace(data);
for(auto& i: indices) i = result.first()[i]; for(auto& i: indices)
i = result.first()[i];
return result.second(); return result.second();
} }
@ -269,7 +270,8 @@ template<class IndexType, class T> std::size_t removeDuplicatesFuzzyIndexedInPla
/* In iteration `0` we're not moving in any dimension, in /* In iteration `0` we're not moving in any dimension, in
iteration `vectorSize` we're moving in `vectorSize - 1` iteration `vectorSize` we're moving in `vectorSize - 1`
dimension */ dimension */
if(vi + 1 == moving) c += moveAmount; if(vi + 1 == moving)
c += moveAmount;
discretizedEntry[vi] = (c - offsets[vi])/epsilon; discretizedEntry[vi] = (c - offsets[vi])/epsilon;
} }
@ -292,7 +294,8 @@ template<class IndexType, class T> std::size_t removeDuplicatesFuzzyIndexedInPla
} }
/* Remap the resulting index array */ /* Remap the resulting index array */
for(auto& i: indices) i = remapping[i]; for(auto& i: indices)
i = remapping[i];
/* Move vertex coordinates by epsilon/2 in the next dimension (which /* Move vertex coordinates by epsilon/2 in the next dimension (which
is moving + 1 in the next loop iteration) */ is moving + 1 in the next loop iteration) */
@ -344,7 +347,8 @@ template<class T> std::size_t removeDuplicatesFuzzyInPlaceIntoImplementation(con
but on MSVC 2015 debug build it excepts StridedArrayIterator to have a but on MSVC 2015 debug build it excepts StridedArrayIterator to have a
member named iterator_category. Fuck that, using a loop instead. */ member named iterator_category. Fuck that, using a loop instead. */
UnsignedInt i = 0; UnsignedInt i = 0;
for(UnsignedInt& index: indices) index = i++; for(UnsignedInt& index: indices)
index = i++;
const std::size_t size = removeDuplicatesFuzzyIndexedInPlaceImplementation(Containers::stridedArrayView(indices), data, epsilon); const std::size_t size = removeDuplicatesFuzzyIndexedInPlaceImplementation(Containers::stridedArrayView(indices), data, epsilon);
return size; return size;

3
src/Magnum/MeshTools/Test/CompileGLTest.cpp

@ -1767,7 +1767,8 @@ void CompileGLTest::externalBuffers() {
}}; }};
/* Duplicate everything if data is non-indexed */ /* Duplicate everything if data is non-indexed */
if(!data.indexed) meshData = duplicate(meshData); if(!data.indexed)
meshData = duplicate(meshData);
GL::Buffer indices{NoCreate}; GL::Buffer indices{NoCreate};
if(meshData.isIndexed()) { if(meshData.isIndexed()) {

6
src/Magnum/MeshTools/Test/InterleaveTest.cpp

@ -1304,7 +1304,8 @@ void InterleaveTest::interleaveMeshDataIndexed() {
/* Testing also offset */ /* Testing also offset */
UnsignedShort indexData[50 + 3]; UnsignedShort indexData[50 + 3];
Containers::StridedArrayView1D<UnsignedShort> indices = Containers::arrayView(indexData).exceptPrefix(50); Containers::StridedArrayView1D<UnsignedShort> indices = Containers::arrayView(indexData).exceptPrefix(50);
if(data.flip) indices = indices.flipped<0>(); if(data.flip)
indices = indices.flipped<0>();
Utility::copy({0, 2, 1}, indices); Utility::copy({0, 2, 1}, indices);
Vector2 positions[]{{1.3f, 0.3f}, {0.87f, 1.1f}, {1.0f, -0.5f}}; Vector2 positions[]{{1.3f, 0.3f}, {0.87f, 1.1f}, {1.0f, -0.5f}};
@ -1551,7 +1552,8 @@ void InterleaveTest::interleaveMeshDataAlreadyInterleavedMoveIndices() {
/* Testing also offset */ /* Testing also offset */
Containers::Array<char> indexData{(50 + 3)*sizeof(UnsignedShort)}; Containers::Array<char> indexData{(50 + 3)*sizeof(UnsignedShort)};
Containers::StridedArrayView1D<UnsignedShort> indices = Containers::arrayCast<UnsignedShort>(indexData).exceptPrefix(50); Containers::StridedArrayView1D<UnsignedShort> indices = Containers::arrayCast<UnsignedShort>(indexData).exceptPrefix(50);
if(data.flip) indices = indices.flipped<0>(); if(data.flip)
indices = indices.flipped<0>();
Utility::copy({0, 2, 1}, indices); Utility::copy({0, 2, 1}, indices);
Containers::Array<char> vertexData{3*8}; Containers::Array<char> vertexData{3*8};

12
src/Magnum/MeshTools/Tipsify.cpp

@ -69,7 +69,8 @@ template<class T> void tipsifyInPlaceImplementation(const Containers::StridedArr
const UnsignedInt t = neighbors[ti]; const UnsignedInt t = neighbors[ti];
/* Continue if already emitted */ /* Continue if already emitted */
if(emitted[t]) continue; if(emitted[t])
continue;
emitted[t] = true; emitted[t] = true;
/* Write all vertices of the triangle to output buffer */ /* Write all vertices of the triangle to output buffer */
@ -99,7 +100,8 @@ template<class T> void tipsifyInPlaceImplementation(const Containers::StridedArr
Int candidatePriority = -1; Int candidatePriority = -1;
for(UnsignedInt v: candidates) { for(UnsignedInt v: candidates) {
/* Skip if it doesn't have any live triangles */ /* Skip if it doesn't have any live triangles */
if(!liveTriangleCount[v]) continue; if(!liveTriangleCount[v])
continue;
/* Get most fresh candidate which will still be in cache even /* Get most fresh candidate which will still be in cache even
after fanning. Every fanned triangle will generate at most after fanning. Every fanned triangle will generate at most
@ -120,7 +122,8 @@ template<class T> void tipsifyInPlaceImplementation(const Containers::StridedArr
UnsignedInt d = deadEndStack.back(); UnsignedInt d = deadEndStack.back();
arrayRemoveSuffix(deadEndStack); arrayRemoveSuffix(deadEndStack);
if(!liveTriangleCount[d]) continue; if(!liveTriangleCount[d])
continue;
fanningVertex = d; fanningVertex = d;
break; break;
} }
@ -128,7 +131,8 @@ template<class T> void tipsifyInPlaceImplementation(const Containers::StridedArr
/* If not found, find next artbitrary vertex with live /* If not found, find next artbitrary vertex with live
triangles */ triangles */
while(++i < vertexCount) { while(++i < vertexCount) {
if(!liveTriangleCount[i]) continue; if(!liveTriangleCount[i])
continue;
fanningVertex = i; fanningVertex = i;
break; break;

24
src/Magnum/MeshTools/Transform.h

@ -61,22 +61,26 @@ Example usage:
@todo GPU transform feedback implementation (otherwise this is only bad joke) @todo GPU transform feedback implementation (otherwise this is only bad joke)
*/ */
template<class T, class U> void transformVectorsInPlace(const Math::Matrix4<T>& matrix, U&& vectors) { template<class T, class U> void transformVectorsInPlace(const Math::Matrix4<T>& matrix, U&& vectors) {
for(auto& vector: vectors) vector = matrix.transformVector(vector); for(auto& vector: vectors)
vector = matrix.transformVector(vector);
} }
/** @overload */ /** @overload */
template<class T, class U> void transformVectorsInPlace(const Math::Matrix3<T>& matrix, U&& vectors) { template<class T, class U> void transformVectorsInPlace(const Math::Matrix3<T>& matrix, U&& vectors) {
for(auto& vector: vectors) vector = matrix.transformVector(vector); for(auto& vector: vectors)
vector = matrix.transformVector(vector);
} }
/** @overload */ /** @overload */
template<class T, class U> void transformVectorsInPlace(const Math::Complex<T>& complex, U&& vectors) { template<class T, class U> void transformVectorsInPlace(const Math::Complex<T>& complex, U&& vectors) {
for(auto& vector: vectors) vector = complex.transformVector(vector); for(auto& vector: vectors)
vector = complex.transformVector(vector);
} }
/** @overload */ /** @overload */
template<class T, class U> void transformVectorsInPlace(const Math::Quaternion<T>& normalizedQuaternion, U&& vectors) { template<class T, class U> void transformVectorsInPlace(const Math::Quaternion<T>& normalizedQuaternion, U&& vectors) {
for(auto& vector: vectors) vector = normalizedQuaternion.transformVectorNormalized(vector); for(auto& vector: vectors)
vector = normalizedQuaternion.transformVectorNormalized(vector);
} }
/** /**
@ -114,22 +118,26 @@ Example usage:
@ref DualQuaternion::transformPointNormalized() @ref DualQuaternion::transformPointNormalized()
*/ */
template<class T, class U> void transformPointsInPlace(const Math::Matrix4<T>& matrix, U&& points) { template<class T, class U> void transformPointsInPlace(const Math::Matrix4<T>& matrix, U&& points) {
for(auto& point: points) point = matrix.transformPoint(point); for(auto& point: points)
point = matrix.transformPoint(point);
} }
/** @overload */ /** @overload */
template<class T, class U> void transformPointsInPlace(const Math::Matrix3<T>& matrix, U&& points) { template<class T, class U> void transformPointsInPlace(const Math::Matrix3<T>& matrix, U&& points) {
for(auto& point: points) point = matrix.transformPoint(point); for(auto& point: points)
point = matrix.transformPoint(point);
} }
/** @overload */ /** @overload */
template<class T, class U> void transformPointsInPlace(const Math::DualComplex<T>& dualComplex, U&& points) { template<class T, class U> void transformPointsInPlace(const Math::DualComplex<T>& dualComplex, U&& points) {
for(auto& point: points) point = dualComplex.transformPoint(point); for(auto& point: points)
point = dualComplex.transformPoint(point);
} }
/** @overload */ /** @overload */
template<class T, class U> void transformPointsInPlace(const Math::DualQuaternion<T>& normalizedDualQuaternion, U&& points) { template<class T, class U> void transformPointsInPlace(const Math::DualQuaternion<T>& normalizedDualQuaternion, U&& points) {
for(auto& point: points) point = normalizedDualQuaternion.transformPointNormalized(point); for(auto& point: points)
point = normalizedDualQuaternion.transformPointNormalized(point);
} }
/** /**

6
src/Magnum/PixelFormat.cpp

@ -1226,7 +1226,8 @@ Magnum::PixelFormat ConfigurationValue<Magnum::PixelFormat>::fromString(Containe
/** @todo This is extremely slow with >100 values. Do a binary search on a /** @todo This is extremely slow with >100 values. Do a binary search on a
sorted index list instead (extracted into a common utility) */ sorted index list instead (extracted into a common utility) */
for(std::size_t i = 0; i != Containers::arraySize(Magnum::PixelFormatNames); ++i) for(std::size_t i = 0; i != Containers::arraySize(Magnum::PixelFormatNames); ++i)
if(stringValue == Magnum::PixelFormatNames[i]) return Magnum::PixelFormat(i + 1); if(stringValue == Magnum::PixelFormatNames[i])
return Magnum::PixelFormat(i + 1);
return {}; return {};
} }
@ -1242,7 +1243,8 @@ Magnum::CompressedPixelFormat ConfigurationValue<Magnum::CompressedPixelFormat>:
/** @todo This is extremely slow with >100 values. Do a binary search on a /** @todo This is extremely slow with >100 values. Do a binary search on a
sorted index list instead (extracted into a common utility) */ sorted index list instead (extracted into a common utility) */
for(std::size_t i = 0; i != Containers::arraySize(Magnum::CompressedPixelFormatNames); ++i) for(std::size_t i = 0; i != Containers::arraySize(Magnum::CompressedPixelFormatNames); ++i)
if(stringValue == Magnum::CompressedPixelFormatNames[i]) return Magnum::CompressedPixelFormat(i + 1); if(stringValue == Magnum::CompressedPixelFormatNames[i])
return Magnum::CompressedPixelFormat(i + 1);
return {}; return {};
} }

15
src/Magnum/Platform/AbstractXApplication.cpp

@ -53,7 +53,8 @@ void AbstractXApplication::create(const Configuration& configuration) {
} }
void AbstractXApplication::create(const Configuration& configuration, const GLConfiguration& glConfiguration) { void AbstractXApplication::create(const Configuration& configuration, const GLConfiguration& glConfiguration) {
if(!tryCreate(configuration, glConfiguration)) std::exit(1); if(!tryCreate(configuration, glConfiguration))
std::exit(1);
} }
bool AbstractXApplication::tryCreate(const Configuration& configuration) { bool AbstractXApplication::tryCreate(const Configuration& configuration) {
@ -119,8 +120,10 @@ AbstractXApplication::~AbstractXApplication() {
_contextHandler.reset(); _contextHandler.reset();
/* Shut down X */ /* Shut down X */
if(_window) XDestroyWindow(_display, _window); if(_window)
if(_display) XCloseDisplay(_display); XDestroyWindow(_display, _window);
if(_display)
XCloseDisplay(_display);
} }
void AbstractXApplication::swapBuffers() { void AbstractXApplication::swapBuffers() {
@ -130,7 +133,8 @@ void AbstractXApplication::swapBuffers() {
int AbstractXApplication::exec() { int AbstractXApplication::exec() {
/* If exit was requested directly in the constructor, exit immediately /* If exit was requested directly in the constructor, exit immediately
without calling anything else */ without calling anything else */
if(_flags & Flag::Exit) return _exitCode; if(_flags & Flag::Exit)
return _exitCode;
/* Show window */ /* Show window */
XMapWindow(_display, _window); XMapWindow(_display, _window);
@ -171,7 +175,8 @@ AbstractXApplication::Pointers buttonsToPointers(const unsigned int state) {
bool AbstractXApplication::mainLoopIteration() { bool AbstractXApplication::mainLoopIteration() {
/* If exit was requested directly in the constructor, exit immediately /* If exit was requested directly in the constructor, exit immediately
without calling anything else */ without calling anything else */
if(_flags & Flag::Exit) return false; if(_flags & Flag::Exit)
return false;
XEvent event; XEvent event;

3
src/Magnum/Platform/AndroidApplication.cpp

@ -103,7 +103,8 @@ void AndroidApplication::create(const Configuration& configuration) {
} }
void AndroidApplication::create(const Configuration& configuration, const GLConfiguration& glConfiguration) { void AndroidApplication::create(const Configuration& configuration, const GLConfiguration& glConfiguration) {
if(!tryCreate(configuration, glConfiguration)) std::exit(32); if(!tryCreate(configuration, glConfiguration))
std::exit(32);
} }
bool AndroidApplication::tryCreate(const Configuration& configuration) { bool AndroidApplication::tryCreate(const Configuration& configuration) {

27
src/Magnum/Platform/EmscriptenApplication.cpp

@ -142,14 +142,17 @@ namespace {
or 'Minus'. Note that the Y key on some layouts may result in 'KeyZ'. */ or 'Minus'. Note that the Y key on some layouts may result in 'KeyZ'. */
Key toKey(const EM_UTF8* const key, const EM_UTF8* const code) { Key toKey(const EM_UTF8* const key, const EM_UTF8* const code) {
const Containers::StringView keyView = key; const Containers::StringView keyView = key;
if(keyView.isEmpty()) return Key::Unknown; if(keyView.isEmpty())
return Key::Unknown;
/* We use key for a-z as it gives us a keyboard layout respecting /* We use key for a-z as it gives us a keyboard layout respecting
representation of the key, i.e. we get `z` for z depending on layout representation of the key, i.e. we get `z` for z depending on layout
where code may give us `y` independent of the layout. */ where code may give us `y` independent of the layout. */
if(keyView.size() == 1) { if(keyView.size() == 1) {
if(key[0] >= 'a' && key[0] <= 'z') return Key(key[0]); if(key[0] >= 'a' && key[0] <= 'z')
else if(key[0] >= 'A' && key[0] <= 'Z') return Key(key[0] - 'A' + 'a'); return Key(key[0]);
else if(key[0] >= 'A' && key[0] <= 'Z')
return Key(key[0] - 'A' + 'a');
} }
/* We use code for 0-9 as it allows us to differentiate towards Numpad /* We use code for 0-9 as it allows us to differentiate towards Numpad
@ -174,7 +177,8 @@ namespace {
/* Numpad0 - Numpad9 */ /* Numpad0 - Numpad9 */
const Int num = numKey[0] - '0'; const Int num = numKey[0] - '0';
if(num >= 0 && num <= 9) return Key(num + Int(Key::NumZero)); if(num >= 0 && num <= 9)
return Key(num + Int(Key::NumZero));
return Key::Unknown; return Key::Unknown;
} }
@ -235,7 +239,8 @@ EmscriptenApplication::EmscriptenApplication(const Arguments& arguments, NoCreat
#endif #endif
/* Save command-line arguments */ /* Save command-line arguments */
if(args.value("log") == "verbose") _verboseLog = true; if(args.value("log") == "verbose")
_verboseLog = true;
const Containers::StringView dpiScaling = args.value<Containers::StringView>("dpi-scaling"); const Containers::StringView dpiScaling = args.value<Containers::StringView>("dpi-scaling");
/* Use physical DPI scaling */ /* Use physical DPI scaling */
@ -273,12 +278,14 @@ void EmscriptenApplication::create() {
} }
void EmscriptenApplication::create(const Configuration& configuration) { void EmscriptenApplication::create(const Configuration& configuration) {
if(!tryCreate(configuration)) exit(1); if(!tryCreate(configuration))
exit(1);
} }
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
void EmscriptenApplication::create(const Configuration& configuration, const GLConfiguration& glConfiguration) { void EmscriptenApplication::create(const Configuration& configuration, const GLConfiguration& glConfiguration) {
if(!tryCreate(configuration, glConfiguration)) exit(32); if(!tryCreate(configuration, glConfiguration))
exit(32);
} }
#endif #endif
@ -1196,7 +1203,8 @@ EmscriptenApplication::GLConfiguration::GLConfiguration():
int EmscriptenApplication::exec() { int EmscriptenApplication::exec() {
/* If exit was requested directly in the constructor, exit immediately /* If exit was requested directly in the constructor, exit immediately
without calling anything else */ without calling anything else */
if(_flags & Flag::ExitRequested) return 0; if(_flags & Flag::ExitRequested)
return 0;
redraw(); redraw();
return 0; return 0;
@ -1208,7 +1216,8 @@ void EmscriptenApplication::redraw() {
/* Loop already running, no need to start, /* Loop already running, no need to start,
Note that should javascript runtimes ever be multithreaded, we Note that should javascript runtimes ever be multithreaded, we
will have a reentrancy issue here. */ will have a reentrancy issue here. */
if(_flags & Flag::LoopActive) return; if(_flags & Flag::LoopActive)
return;
/* Start requestAnimationFrame loop */ /* Start requestAnimationFrame loop */
_flags |= Flag::LoopActive; _flags |= Flag::LoopActive;

45
src/Magnum/Platform/GlfwApplication.cpp

@ -139,7 +139,8 @@ GlfwApplication::GlfwApplication(const Arguments& arguments, NoCreateT):
#endif #endif
/* Save command-line arguments */ /* Save command-line arguments */
if(args.value("log") == "verbose") _verboseLog = true; if(args.value("log") == "verbose")
_verboseLog = true;
const Containers::StringView dpiScaling = args.value<Containers::StringView>("dpi-scaling"); const Containers::StringView dpiScaling = args.value<Containers::StringView>("dpi-scaling");
if(dpiScaling == "default"_s) if(dpiScaling == "default"_s)
_commandLineDpiScalingPolicy = Implementation::GlfwDpiScalingPolicy::Default; _commandLineDpiScalingPolicy = Implementation::GlfwDpiScalingPolicy::Default;
@ -163,12 +164,14 @@ void GlfwApplication::create() {
} }
void GlfwApplication::create(const Configuration& configuration) { void GlfwApplication::create(const Configuration& configuration) {
if(!tryCreate(configuration)) std::exit(1); if(!tryCreate(configuration))
std::exit(1);
} }
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
void GlfwApplication::create(const Configuration& configuration, const GLConfiguration& glConfiguration) { void GlfwApplication::create(const Configuration& configuration, const GLConfiguration& glConfiguration) {
if(!tryCreate(configuration, glConfiguration)) std::exit(1); if(!tryCreate(configuration, glConfiguration))
std::exit(1);
} }
#endif #endif
@ -676,7 +679,8 @@ void GlfwApplication::setupCallbacks() {
glfwSetWindowCloseCallback(_window, [](GLFWwindow* const window){ glfwSetWindowCloseCallback(_window, [](GLFWwindow* const window){
ExitEvent e; ExitEvent e;
static_cast<GlfwApplication*>(glfwGetWindowUserPointer(window))->exitEvent(e); static_cast<GlfwApplication*>(glfwGetWindowUserPointer(window))->exitEvent(e);
if(!e.isAccepted()) glfwSetWindowShouldClose(window, false); if(!e.isAccepted())
glfwSetWindowShouldClose(window, false);
}); });
glfwSetWindowRefreshCallback(_window, [](GLFWwindow* const window){ glfwSetWindowRefreshCallback(_window, [](GLFWwindow* const window){
/* Properly redraw after the window is restored from minimized state */ /* Properly redraw after the window is restored from minimized state */
@ -758,7 +762,8 @@ void GlfwApplication::setupCallbacks() {
glfwSetCharCallback(_window, [](GLFWwindow* window, unsigned int codepoint) { glfwSetCharCallback(_window, [](GLFWwindow* window, unsigned int codepoint) {
auto& app = *static_cast<GlfwApplication*>(glfwGetWindowUserPointer(window)); auto& app = *static_cast<GlfwApplication*>(glfwGetWindowUserPointer(window));
if(!(app._flags & Flag::TextInputActive)) return; if(!(app._flags & Flag::TextInputActive))
return;
/* One extra byte to ensure it gets always null-terminated */ /* One extra byte to ensure it gets always null-terminated */
char utf8[4 + 1]{}; char utf8[4 + 1]{};
@ -846,7 +851,8 @@ void GlfwApplication::setSwapInterval(const Int interval) {
minimal loop period or not. Unlike SDL2 where it's possible to check minimal loop period or not. Unlike SDL2 where it's possible to check
whether the VSync was actually set, here it's purely hope-based. whether the VSync was actually set, here it's purely hope-based.
Sorry. */ Sorry. */
if(interval) _flags |= Flag::VSyncEnabled; if(interval)
_flags |= Flag::VSyncEnabled;
else _flags &= ~Flag::VSyncEnabled; else _flags &= ~Flag::VSyncEnabled;
} }
@ -867,7 +873,8 @@ int GlfwApplication::exec() {
bool GlfwApplication::mainLoopIteration() { bool GlfwApplication::mainLoopIteration() {
/* If exit was requested directly in the constructor, exit immediately /* If exit was requested directly in the constructor, exit immediately
without calling anything else */ without calling anything else */
if(_flags & Flag::Exit || glfwWindowShouldClose(_window)) return false; if(_flags & Flag::Exit || glfwWindowShouldClose(_window))
return false;
CORRADE_ASSERT(_window, "Platform::GlfwApplication::mainLoopIteration(): no window opened", {}); CORRADE_ASSERT(_window, "Platform::GlfwApplication::mainLoopIteration(): no window opened", {});
@ -891,14 +898,16 @@ bool GlfwApplication::mainLoopIteration() {
which point the vtable pointers for the derived class are not set which point the vtable pointers for the derived class are not set
up yet). up yet).
*/ */
if(glfwGetWindowUserPointer(_window) != this) setupCallbacks(); if(glfwGetWindowUserPointer(_window) != this)
setupCallbacks();
const Nanoseconds timeBefore = _minimalLoopPeriodNanoseconds ? glfwGetTime()*1.0_sec : Nanoseconds{}; const Nanoseconds timeBefore = _minimalLoopPeriodNanoseconds ? glfwGetTime()*1.0_sec : Nanoseconds{};
glfwPollEvents(); glfwPollEvents();
/* Tick event */ /* Tick event */
if(!(_flags & Flag::NoTickEvent)) tickEvent(); if(!(_flags & Flag::NoTickEvent))
tickEvent();
/* Draw event */ /* Draw event */
if(_flags & Flag::Redraw) { if(_flags & Flag::Redraw) {
@ -924,7 +933,8 @@ bool GlfwApplication::mainLoopIteration() {
/* Then, if the tick event doesn't need to be called periodically, wait /* Then, if the tick event doesn't need to be called periodically, wait
indefinitely for next input event */ indefinitely for next input event */
if(_flags & Flag::NoTickEvent) glfwWaitEvents(); if(_flags & Flag::NoTickEvent)
glfwWaitEvents();
return !(_flags & Flag::Exit || glfwWindowShouldClose(_window)); return !(_flags & Flag::Exit || glfwWindowShouldClose(_window));
} }
@ -934,7 +944,8 @@ void GlfwApplication::exit(int exitCode) {
/* If the window is already created, tell GLFW that it should close. If /* If the window is already created, tell GLFW that it should close. If
not, this is done in tryCreate() once the window is created */ not, this is done in tryCreate() once the window is created */
if(_window) glfwSetWindowShouldClose(_window, true); if(_window)
glfwSetWindowShouldClose(_window, true);
} }
bool GlfwApplication::isKeyPressed(const Key key) { bool GlfwApplication::isKeyPressed(const Key key) {
@ -1195,7 +1206,8 @@ GlfwApplication::Pointers GlfwApplication::PointerMoveEvent::pointers() {
} }
GlfwApplication::Modifiers GlfwApplication::PointerMoveEvent::modifiers() { GlfwApplication::Modifiers GlfwApplication::PointerMoveEvent::modifiers() {
if(!_modifiers) _modifiers = currentGlfwModifiers(_window); if(!_modifiers)
_modifiers = currentGlfwModifiers(_window);
return *_modifiers; return *_modifiers;
} }
@ -1216,14 +1228,16 @@ auto GlfwApplication::MouseMoveEvent::buttons() -> Buttons {
} }
GlfwApplication::Modifiers GlfwApplication::MouseMoveEvent::modifiers() { GlfwApplication::Modifiers GlfwApplication::MouseMoveEvent::modifiers() {
if(!_modifiers) _modifiers = currentGlfwModifiers(_window); if(!_modifiers)
_modifiers = currentGlfwModifiers(_window);
return *_modifiers; return *_modifiers;
} }
CORRADE_IGNORE_DEPRECATED_POP CORRADE_IGNORE_DEPRECATED_POP
#endif #endif
GlfwApplication::Modifiers GlfwApplication::ScrollEvent::modifiers() { GlfwApplication::Modifiers GlfwApplication::ScrollEvent::modifiers() {
if(!_modifiers) _modifiers = currentGlfwModifiers(_window); if(!_modifiers)
_modifiers = currentGlfwModifiers(_window);
return *_modifiers; return *_modifiers;
} }
Vector2 GlfwApplication::ScrollEvent::position() { Vector2 GlfwApplication::ScrollEvent::position() {
@ -1248,7 +1262,8 @@ Vector2i GlfwApplication::MouseScrollEvent::position() {
} }
GlfwApplication::Modifiers GlfwApplication::MouseScrollEvent::modifiers() { GlfwApplication::Modifiers GlfwApplication::MouseScrollEvent::modifiers() {
if(!_modifiers) _modifiers = currentGlfwModifiers(_window); if(!_modifiers)
_modifiers = currentGlfwModifiers(_window);
return *_modifiers; return *_modifiers;
} }
CORRADE_IGNORE_DEPRECATED_POP CORRADE_IGNORE_DEPRECATED_POP

48
src/Magnum/Platform/ScreenedApplication.hpp

@ -43,7 +43,8 @@ template<class Application> void ApplicationKeyEventMixin<Application, true>::ca
for(BasicScreen<Application>* s = screens.first(); s; s = s->nextFartherScreen()) { for(BasicScreen<Application>* s = screens.first(); s; s = s->nextFartherScreen()) {
if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) { if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) {
s->keyPressEvent(event); s->keyPressEvent(event);
if(event.isAccepted()) break; if(event.isAccepted())
break;
} }
} }
} }
@ -54,7 +55,8 @@ template<class Application> void ApplicationKeyEventMixin<Application, true>::ca
for(BasicScreen<Application>* s = screens.first(); s; s = s->nextFartherScreen()) { for(BasicScreen<Application>* s = screens.first(); s; s = s->nextFartherScreen()) {
if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) { if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) {
s->keyReleaseEvent(event); s->keyReleaseEvent(event);
if(event.isAccepted()) break; if(event.isAccepted())
break;
} }
} }
} }
@ -65,7 +67,8 @@ template<class Application> void ApplicationScrollEventMixin<Application, true>:
for(BasicScreen<Application>* s = screens.first(); s; s = s->nextFartherScreen()) { for(BasicScreen<Application>* s = screens.first(); s; s = s->nextFartherScreen()) {
if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) { if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) {
s->scrollEvent(event); s->scrollEvent(event);
if(event.isAccepted()) break; if(event.isAccepted())
break;
} }
} }
@ -89,7 +92,8 @@ template<class Application> void ApplicationMouseScrollEventMixin<Application, t
for(BasicScreen<Application>* s = screens.first(); s; s = s->nextFartherScreen()) { for(BasicScreen<Application>* s = screens.first(); s; s = s->nextFartherScreen()) {
if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) { if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) {
s->mouseScrollEvent(event); s->mouseScrollEvent(event);
if(event.isAccepted()) break; if(event.isAccepted())
break;
} }
} }
} }
@ -102,7 +106,8 @@ template<class Application> void ApplicationTextInputEventMixin<Application, tru
for(BasicScreen<Application>* s = screens.first(); s; s = s->nextFartherScreen()) { for(BasicScreen<Application>* s = screens.first(); s; s = s->nextFartherScreen()) {
if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) { if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) {
s->textInputEvent(event); s->textInputEvent(event);
if(event.isAccepted()) break; if(event.isAccepted())
break;
} }
} }
} }
@ -114,7 +119,8 @@ true>::callTextEditingEvent(typename Application::TextEditingEvent& event, Conta
for(BasicScreen<Application>* s = screens.first(); s; s = s->nextFartherScreen()) { for(BasicScreen<Application>* s = screens.first(); s; s = s->nextFartherScreen()) {
if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) { if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) {
s->textEditingEvent(event); s->textEditingEvent(event);
if(event.isAccepted()) break; if(event.isAccepted())
break;
} }
} }
} }
@ -199,7 +205,8 @@ template<class Application> BasicScreenedApplication<Application>& BasicScreened
BasicScreen(BasicScreenedApplication&, PropagatedEvents) as well. Keep BasicScreen(BasicScreenedApplication&, PropagatedEvents) as well. Keep
in sync. */ in sync. */
Containers::LinkedList<BasicScreen<Application>>::insert(&screen); Containers::LinkedList<BasicScreen<Application>>::insert(&screen);
if(screens().first() == &screen) screen.focusEvent(); if(screens().first() == &screen)
screen.focusEvent();
Application::redraw(); Application::redraw();
return *this; return *this;
} }
@ -219,7 +226,8 @@ template<class Application> BasicScreenedApplication<Application>& BasicScreened
"Platform::ScreenedApplication::focusScreen(): screen not owned by this application", *this); "Platform::ScreenedApplication::focusScreen(): screen not owned by this application", *this);
/* Already focused, nothing to do */ /* Already focused, nothing to do */
if(screens().first() == &screen) return *this; if(screens().first() == &screen)
return *this;
screens().first()->blurEvent(); screens().first()->blurEvent();
Containers::LinkedList<BasicScreen<Application>>::move(&screen, screens().first()); Containers::LinkedList<BasicScreen<Application>>::move(&screen, screens().first());
@ -234,7 +242,8 @@ template<class Application> void BasicScreenedApplication<Application>::viewport
/* Call global event before all other (to resize framebuffer first) */ /* Call global event before all other (to resize framebuffer first) */
globalViewportEvent(event); globalViewportEvent(event);
for(BasicScreen<Application>& s: *this) s.viewportEvent(event); for(BasicScreen<Application>& s: *this)
s.viewportEvent(event);
} }
template<class Application> void BasicScreenedApplication<Application>::globalBeforeDrawEvent() {} template<class Application> void BasicScreenedApplication<Application>::globalBeforeDrawEvent() {}
@ -245,7 +254,8 @@ template<class Application> void BasicScreenedApplication<Application>::drawEven
/* Back-to-front rendering */ /* Back-to-front rendering */
for(BasicScreen<Application>* s = screens().last(); s; s = s->nextNearerScreen()) for(BasicScreen<Application>* s = screens().last(); s; s = s->nextNearerScreen())
if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Draw) s->drawEvent(); if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Draw)
s->drawEvent();
/* Call global event after all other (to swap buffers last) */ /* Call global event after all other (to swap buffers last) */
globalDrawEvent(); globalDrawEvent();
@ -264,7 +274,8 @@ template<class Application> void BasicScreenedApplication<Application>::pointerP
for(BasicScreen<Application>* s = screens().first(); s; s = s->nextFartherScreen()) { for(BasicScreen<Application>* s = screens().first(); s; s = s->nextFartherScreen()) {
if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) { if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) {
s->pointerPressEvent(event); s->pointerPressEvent(event);
if(event.isAccepted()) break; if(event.isAccepted())
break;
} }
} }
@ -283,7 +294,8 @@ template<class Application> void BasicScreenedApplication<Application>::pointerR
for(BasicScreen<Application>* s = screens().first(); s; s = s->nextFartherScreen()) { for(BasicScreen<Application>* s = screens().first(); s; s = s->nextFartherScreen()) {
if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) { if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) {
s->pointerReleaseEvent(event); s->pointerReleaseEvent(event);
if(event.isAccepted()) break; if(event.isAccepted())
break;
} }
} }
@ -302,7 +314,8 @@ template<class Application> void BasicScreenedApplication<Application>::pointerM
for(BasicScreen<Application>* s = screens().first(); s; s = s->nextFartherScreen()) { for(BasicScreen<Application>* s = screens().first(); s; s = s->nextFartherScreen()) {
if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) { if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) {
s->pointerMoveEvent(event); s->pointerMoveEvent(event);
if(event.isAccepted()) break; if(event.isAccepted())
break;
} }
} }
@ -323,7 +336,8 @@ template<class Application> void BasicScreenedApplication<Application>::mousePre
for(BasicScreen<Application>* s = screens().first(); s; s = s->nextFartherScreen()) { for(BasicScreen<Application>* s = screens().first(); s; s = s->nextFartherScreen()) {
if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) { if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) {
s->mousePressEvent(event); s->mousePressEvent(event);
if(event.isAccepted()) break; if(event.isAccepted())
break;
} }
} }
} }
@ -333,7 +347,8 @@ template<class Application> void BasicScreenedApplication<Application>::mouseRel
for(BasicScreen<Application>* s = screens().first(); s; s = s->nextFartherScreen()) { for(BasicScreen<Application>* s = screens().first(); s; s = s->nextFartherScreen()) {
if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) { if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) {
s->mouseReleaseEvent(event); s->mouseReleaseEvent(event);
if(event.isAccepted()) break; if(event.isAccepted())
break;
} }
} }
} }
@ -343,7 +358,8 @@ template<class Application> void BasicScreenedApplication<Application>::mouseMov
for(BasicScreen<Application>* s = screens().first(); s; s = s->nextFartherScreen()) { for(BasicScreen<Application>* s = screens().first(); s; s = s->nextFartherScreen()) {
if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) { if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) {
s->mouseMoveEvent(event); s->mouseMoveEvent(event);
if(event.isAccepted()) break; if(event.isAccepted())
break;
} }
} }
} }

54
src/Magnum/Platform/Sdl2Application.cpp

@ -248,7 +248,8 @@ Sdl2Application::Sdl2Application(const Arguments& arguments, NoCreateT):
} }
/* Save command-line arguments */ /* Save command-line arguments */
if(args.value("log") == "verbose") _verboseLog = true; if(args.value("log") == "verbose")
_verboseLog = true;
const Containers::StringView dpiScaling = args.value<Containers::StringView>("dpi-scaling"); const Containers::StringView dpiScaling = args.value<Containers::StringView>("dpi-scaling");
if(dpiScaling == "default"_s) if(dpiScaling == "default"_s)
_commandLineDpiScalingPolicy = Implementation::Sdl2DpiScalingPolicy::Default; _commandLineDpiScalingPolicy = Implementation::Sdl2DpiScalingPolicy::Default;
@ -275,12 +276,14 @@ void Sdl2Application::create() {
} }
void Sdl2Application::create(const Configuration& configuration) { void Sdl2Application::create(const Configuration& configuration) {
if(!tryCreate(configuration)) std::exit(1); if(!tryCreate(configuration))
std::exit(1);
} }
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
void Sdl2Application::create(const Configuration& configuration, const GLConfiguration& glConfiguration) { void Sdl2Application::create(const Configuration& configuration, const GLConfiguration& glConfiguration) {
if(!tryCreate(configuration, glConfiguration)) std::exit(1); if(!tryCreate(configuration, glConfiguration))
std::exit(1);
} }
#endif #endif
@ -897,7 +900,8 @@ bool Sdl2Application::setSwapInterval(const Int interval) {
return false; return false;
} }
if(interval) _flags |= Flag::VSyncEnabled; if(interval)
_flags |= Flag::VSyncEnabled;
else _flags &= ~Flag::VSyncEnabled; else _flags &= ~Flag::VSyncEnabled;
return true; return true;
} }
@ -930,9 +934,11 @@ Sdl2Application::~Sdl2Application() {
_context = Containers::NullOpt; _context = Containers::NullOpt;
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
if(_glContext) SDL_GL_DeleteContext(_glContext); if(_glContext)
SDL_GL_DeleteContext(_glContext);
#else #else
if(_surface) SDL_FreeSurface(_surface); if(_surface)
SDL_FreeSurface(_surface);
#endif #endif
#endif #endif
@ -942,7 +948,8 @@ Sdl2Application::~Sdl2Application() {
#endif #endif
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
if(_window) SDL_DestroyWindow(_window); if(_window)
SDL_DestroyWindow(_window);
#endif #endif
SDL_Quit(); SDL_Quit();
} }
@ -1007,7 +1014,8 @@ Sdl2Application::Pointers buttonsToPointers(const Uint32 buttons) {
bool Sdl2Application::mainLoopIteration() { bool Sdl2Application::mainLoopIteration() {
/* If exit was requested directly in the constructor, exit immediately /* If exit was requested directly in the constructor, exit immediately
without calling anything else */ without calling anything else */
if(_flags & Flag::Exit) return false; if(_flags & Flag::Exit)
return false;
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
CORRADE_ASSERT(_window, "Platform::Sdl2Application::mainLoopIteration(): no window opened", {}); CORRADE_ASSERT(_window, "Platform::Sdl2Application::mainLoopIteration(): no window opened", {});
@ -1084,10 +1092,12 @@ bool Sdl2Application::mainLoopIteration() {
things not present in the Application APIs */ things not present in the Application APIs */
case SDL_WINDOWEVENT_EXPOSED: case SDL_WINDOWEVENT_EXPOSED:
_flags |= Flag::Redraw; _flags |= Flag::Redraw;
if(!(_flags & Flag::NoAnyEvent)) anyEvent(event); if(!(_flags & Flag::NoAnyEvent))
anyEvent(event);
break; break;
default: default:
if(!(_flags & Flag::NoAnyEvent)) anyEvent(event); if(!(_flags & Flag::NoAnyEvent))
anyEvent(event);
} break; } break;
case SDL_KEYDOWN: case SDL_KEYDOWN:
@ -1282,12 +1292,14 @@ bool Sdl2Application::mainLoopIteration() {
/* Direct everything else to anyEvent(), so users can implement /* Direct everything else to anyEvent(), so users can implement
event handling for things not present in the Application APIs */ event handling for things not present in the Application APIs */
default: if(!(_flags & Flag::NoAnyEvent)) anyEvent(event); default: if(!(_flags & Flag::NoAnyEvent))
anyEvent(event);
} }
} }
/* Tick event */ /* Tick event */
if(!(_flags & Flag::NoTickEvent)) tickEvent(); if(!(_flags & Flag::NoTickEvent))
tickEvent();
/* Draw event */ /* Draw event */
if(_flags & Flag::Redraw) { if(_flags & Flag::Redraw) {
@ -1316,7 +1328,8 @@ bool Sdl2Application::mainLoopIteration() {
/* Then, if the tick event doesn't need to be called periodically, wait /* Then, if the tick event doesn't need to be called periodically, wait
indefinitely for next input event */ indefinitely for next input event */
if(_flags & Flag::NoTickEvent) SDL_WaitEvent(nullptr); if(_flags & Flag::NoTickEvent)
SDL_WaitEvent(nullptr);
#endif #endif
return !(_flags & Flag::Exit); return !(_flags & Flag::Exit);
} }
@ -1416,7 +1429,8 @@ Sdl2Application::Cursor Sdl2Application::cursor() {
SDL_Cursor* cursor = SDL_GetCursor(); SDL_Cursor* cursor = SDL_GetCursor();
if(cursor) for(UnsignedInt i = 0; i < sizeof(_cursors); i++) if(cursor) for(UnsignedInt i = 0; i < sizeof(_cursors); i++)
if(_cursors[i] == cursor) return Cursor(i); if(_cursors[i] == cursor)
return Cursor(i);
return Cursor::Arrow; return Cursor::Arrow;
#else #else
@ -1713,7 +1727,8 @@ Sdl2Application::Modifiers Sdl2Application::PointerEvent::modifiers() {
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_IGNORE_DEPRECATED_PUSH CORRADE_IGNORE_DEPRECATED_PUSH
Sdl2Application::Modifiers Sdl2Application::MouseEvent::modifiers() { Sdl2Application::Modifiers Sdl2Application::MouseEvent::modifiers() {
if(_modifiers) return *_modifiers; if(_modifiers)
return *_modifiers;
return *(_modifiers = fixedModifiers(Uint16(SDL_GetModState()))); return *(_modifiers = fixedModifiers(Uint16(SDL_GetModState())));
} }
CORRADE_IGNORE_DEPRECATED_POP CORRADE_IGNORE_DEPRECATED_POP
@ -1728,7 +1743,8 @@ Sdl2Application::Modifiers Sdl2Application::PointerMoveEvent::modifiers() {
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_IGNORE_DEPRECATED_PUSH CORRADE_IGNORE_DEPRECATED_PUSH
Sdl2Application::Modifiers Sdl2Application::MouseMoveEvent::modifiers() { Sdl2Application::Modifiers Sdl2Application::MouseMoveEvent::modifiers() {
if(_modifiers) return *_modifiers; if(_modifiers)
return *_modifiers;
return *(_modifiers = fixedModifiers(Uint16(SDL_GetModState()))); return *(_modifiers = fixedModifiers(Uint16(SDL_GetModState())));
} }
CORRADE_IGNORE_DEPRECATED_POP CORRADE_IGNORE_DEPRECATED_POP
@ -1755,14 +1771,16 @@ Sdl2Application::Modifiers Sdl2Application::ScrollEvent::modifiers() {
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_IGNORE_DEPRECATED_PUSH CORRADE_IGNORE_DEPRECATED_PUSH
Vector2i Sdl2Application::MouseScrollEvent::position() { Vector2i Sdl2Application::MouseScrollEvent::position() {
if(_position) return *_position; if(_position)
return *_position;
_position = Vector2i{}; _position = Vector2i{};
SDL_GetMouseState(&_position->x(), &_position->y()); SDL_GetMouseState(&_position->x(), &_position->y());
return *_position; return *_position;
} }
Sdl2Application::Modifiers Sdl2Application::MouseScrollEvent::modifiers() { Sdl2Application::Modifiers Sdl2Application::MouseScrollEvent::modifiers() {
if(_modifiers) return *_modifiers; if(_modifiers)
return *_modifiers;
return *(_modifiers = fixedModifiers(Uint16(SDL_GetModState()))); return *(_modifiers = fixedModifiers(Uint16(SDL_GetModState())));
} }
CORRADE_IGNORE_DEPRECATED_POP CORRADE_IGNORE_DEPRECATED_POP

3
src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp

@ -386,7 +386,8 @@ struct EmscriptenApplicationTest: Platform::Application {
} else if(event.key() == Key::F2) { } else if(event.key() == Key::F2) {
_redraw = !_redraw; _redraw = !_redraw;
Debug{} << "redrawing" << (_redraw ? "enabled" : "disabled"); Debug{} << "redrawing" << (_redraw ? "enabled" : "disabled");
if(_redraw) redraw(); if(_redraw)
redraw();
} else if(event.key() == Key::Esc) { } else if(event.key() == Key::Esc) {
Debug{} << "stopping text input"; Debug{} << "stopping text input";
stopTextInput(); stopTextInput();

3
src/Magnum/Platform/Test/GlfwApplicationTest.cpp

@ -322,7 +322,8 @@ struct GlfwApplicationTest: Platform::Application {
} else if(event.key() == Key::F2) { } else if(event.key() == Key::F2) {
_redraw = !_redraw; _redraw = !_redraw;
Debug{} << "redrawing" << (_redraw ? "enabled" : "disabled"); Debug{} << "redrawing" << (_redraw ? "enabled" : "disabled");
if(_redraw) redraw(); if(_redraw)
redraw();
} else if(event.key() == Key::V && !event.modifiers()) { } else if(event.key() == Key::V && !event.modifiers()) {
_vsync = !_vsync; _vsync = !_vsync;
Debug{} << "vsync" << (_vsync? "on" : "off"); Debug{} << "vsync" << (_vsync? "on" : "off");

6
src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp

@ -405,7 +405,8 @@ struct Sdl2ApplicationTest: Platform::Application {
} else if(event.key() == Key::F2) { } else if(event.key() == Key::F2) {
_redraw = !_redraw; _redraw = !_redraw;
Debug{} << "redrawing" << (_redraw ? "enabled" : "disabled"); Debug{} << "redrawing" << (_redraw ? "enabled" : "disabled");
if(_redraw) redraw(); if(_redraw)
redraw();
} }
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
else if(event.key() == Key::V && !(event.modifiers() & ~(Modifier::CapsLock|Modifier::NumLock))) { else if(event.key() == Key::V && !(event.modifiers() & ~(Modifier::CapsLock|Modifier::NumLock))) {
@ -500,7 +501,8 @@ struct Sdl2ApplicationTest: Platform::Application {
void anyEvent(SDL_Event& event) override { void anyEvent(SDL_Event& event) override {
Debug d; Debug d;
d << "any event:" << event.type; d << "any event:" << event.type;
if(event.type == SDL_WINDOWEVENT) d << event.window.event; if(event.type == SDL_WINDOWEVENT)
d << event.window.event;
} }
/* Uncomment to test the tick event. It should run at given minimal loop /* Uncomment to test the tick event. It should run at given minimal loop

9
src/Magnum/Platform/WindowlessCglApplication.cpp

@ -79,8 +79,10 @@ WindowlessCglContext::WindowlessCglContext(WindowlessCglContext&& other) noexcep
} }
WindowlessCglContext::~WindowlessCglContext() { WindowlessCglContext::~WindowlessCglContext() {
if(_context) CGLDestroyContext(_context); if(_context)
if(_pixelFormat) CGLDestroyPixelFormat(_pixelFormat); CGLDestroyContext(_context);
if(_pixelFormat)
CGLDestroyPixelFormat(_pixelFormat);
} }
WindowlessCglContext& WindowlessCglContext::operator=(WindowlessCglContext&& other) noexcept { WindowlessCglContext& WindowlessCglContext::operator=(WindowlessCglContext&& other) noexcept {
@ -121,7 +123,8 @@ WindowlessCglApplication::~WindowlessCglApplication() = default;
void WindowlessCglApplication::createContext() { createContext({}); } void WindowlessCglApplication::createContext() { createContext({}); }
void WindowlessCglApplication::createContext(const Configuration& configuration) { void WindowlessCglApplication::createContext(const Configuration& configuration) {
if(!tryCreateContext(configuration)) std::exit(1); if(!tryCreateContext(configuration))
std::exit(1);
} }
bool WindowlessCglApplication::tryCreateContext(const Configuration& configuration) { bool WindowlessCglApplication::tryCreateContext(const Configuration& configuration) {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save