diff --git a/doc/compilation-speedup.dox b/doc/compilation-speedup.dox index c1a0802f6..13dfef0ee 100644 --- a/doc/compilation-speedup.dox +++ b/doc/compilation-speedup.dox @@ -17,7 +17,11 @@ Math/Vector3.h. You are encouraged to use forward declarations also in your code. However, for some types it can be too cumbersome -- e.g. too many template parameters, typedefs etc. In this case a header with forward declarations is usually -available: see SceneGraph/SceneGraph.h for example. +available, each namespace has its own: + + - Magnum.h + - SceneGraph/SceneGraph.h + - Shaders/Shaders.h @section compilation-speedup-templates Templates diff --git a/src/AbstractShaderProgram.cpp b/src/AbstractShaderProgram.cpp index e02831f1a..cb181b9b4 100644 --- a/src/AbstractShaderProgram.cpp +++ b/src/AbstractShaderProgram.cpp @@ -73,6 +73,16 @@ AbstractShaderProgram::UniformMatrix3x4dvImplementation AbstractShaderProgram::u AbstractShaderProgram::UniformMatrix4x3dvImplementation AbstractShaderProgram::uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; #endif +GLint AbstractShaderProgram::maxSupportedVertexAttributeCount() { + GLint& value = Context::current()->state()->shaderProgram->maxSupportedVertexAttributeCount; + + /* Get the value, if not already cached */ + if(value == 0) + glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &value); + + return value; +} + AbstractShaderProgram::~AbstractShaderProgram() { /* Remove current usage from the state */ GLuint& current = Context::current()->state()->shaderProgram->current; diff --git a/src/AbstractShaderProgram.h b/src/AbstractShaderProgram.h index 7f85beeaf..7729a25cb 100644 --- a/src/AbstractShaderProgram.h +++ b/src/AbstractShaderProgram.h @@ -19,7 +19,6 @@ * @brief Class Magnum::AbstractShaderProgram */ -#include #include #include @@ -38,11 +37,6 @@ namespace Math { template class Vector; } -template class Color3; -template class Color4; -class Context; -class Shader; - #ifndef DOXYGEN_GENERATING_OUTPUT namespace Implementation { template struct Attribute; @@ -273,7 +267,8 @@ vertex attributes. See also TypeTraits::AttributeType. @section AbstractShaderProgram-performance-optimization Performance optimizations The engine tracks currently used shader program to avoid unnecessary calls to -@fn_gl{UseProgram}. +@fn_gl{UseProgram}. %Shader limits (such as maxSupportedVertexAttributeCount()) +are cached, so repeated queries don't result in repeated @fn_gl{Get} calls. If extension @extension{ARB,separate_shader_objects} or @extension{EXT,direct_state_access} is available, uniform setting functions @@ -297,6 +292,11 @@ class MAGNUM_EXPORT AbstractShaderProgram { /** * @brief Base struct for attribute location and type * + * Template parameter @p location is vertex attribute location, number + * between `0` and maxSupportedVertexAttributeCount(). To ensure + * compatibility, you should always have vertex attribute with + * location `0`. + * * Template parameter @p T is the type which is used for shader * attribute, e.g. @ref Math::Vector4 "Vector4" for `ivec4`. * DataType is type of passed data when adding vertex buffers to mesh. @@ -315,10 +315,10 @@ class MAGNUM_EXPORT AbstractShaderProgram { * shaders and @ref Mesh-configuration for example usage when adding * vertex buffers to mesh. */ - template class Attribute { + template class Attribute { public: /** @brief Location to which the attribute is bound */ - static const GLuint Location = i; + static const GLuint Location = location; /** * @brief Type @@ -441,6 +441,15 @@ class MAGNUM_EXPORT AbstractShaderProgram { const DataOptions _dataOptions; }; + /** + * @brief Max supported vertex attribute count + * + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. + * @see Attribute, @fn_gl{Get} with @def_gl{MAX_VERTEX_ATTRIBS} + */ + static GLint maxSupportedVertexAttributeCount(); + /** * @brief Constructor * diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h index bcfe10cf5..a9942dffe 100644 --- a/src/AbstractTexture.h +++ b/src/AbstractTexture.h @@ -19,16 +19,12 @@ * @brief Class Magnum::AbstractTexture */ -#include - #include "Magnum.h" #include "Color.h" #include "AbstractImage.h" namespace Magnum { -class Context; - /** @brief Base for textures @@ -576,7 +572,10 @@ class MAGNUM_EXPORT AbstractTexture { /** * @brief Max supported layer count * - * @see bind(GLint), @fn_gl{Get} with @def_gl{MAX_COMBINED_TEXTURE_IMAGE_UNITS}, + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. + * @see @ref AbstractShaderProgram-subclassing, bind(GLint), + * @fn_gl{Get} with @def_gl{MAX_COMBINED_TEXTURE_IMAGE_UNITS}, * @fn_gl{ActiveTexture} */ static GLint maxSupportedLayerCount(); @@ -584,6 +583,8 @@ class MAGNUM_EXPORT AbstractTexture { /** * @brief Max supported anisotropy * + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. * @see setMaxAnisotropy(), @fn_gl{Get} with @def_gl{MAX_TEXTURE_MAX_ANISOTROPY_EXT} * @requires_extension %Extension @extension{EXT,texture_filter_anisotropic} * @requires_es_extension %Extension @es_extension2{EXT,texture_filter_anisotropic,texture_filter_anisotropic} diff --git a/src/Buffer.h b/src/Buffer.h index bf426f2d4..7473543ff 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -29,8 +29,6 @@ namespace Magnum { -class Context; - /** @brief %Buffer diff --git a/src/BufferedTexture.h b/src/BufferedTexture.h index 170f606b9..87f478ee0 100644 --- a/src/BufferedTexture.h +++ b/src/BufferedTexture.h @@ -26,9 +26,6 @@ #ifndef MAGNUM_TARGET_GLES namespace Magnum { -class Buffer; -class Context; - /** @brief Buffered texture diff --git a/src/Color.h b/src/Color.h index 6af5ba7d5..36d4ad4c8 100644 --- a/src/Color.h +++ b/src/Color.h @@ -24,11 +24,10 @@ #include "Math/MathTypeTraits.h" #include "Math/Math.h" #include "Math/Vector4.h" +#include "Magnum.h" namespace Magnum { -template class Color3; - #ifndef DOXYGEN_GENERATING_OUTPUT namespace Implementation { diff --git a/src/DimensionTraits.h b/src/DimensionTraits.h index 218a88f05..2424c40d8 100644 --- a/src/DimensionTraits.h +++ b/src/DimensionTraits.h @@ -16,7 +16,6 @@ */ #include -#include #include "Magnum.h" diff --git a/src/Framebuffer.h b/src/Framebuffer.h index e18fe083d..6099ecea1 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -29,20 +29,6 @@ namespace Magnum { -#ifndef MAGNUM_TARGET_GLES2 -template class BufferedImage; -#endif -template class Image; - -#ifndef MAGNUM_TARGET_GLES2 -typedef BufferedImage<1> BufferedImage1D; -typedef BufferedImage<2> BufferedImage2D; -typedef BufferedImage<3> BufferedImage3D; -#endif -typedef Image<1> Image1D; -typedef Image<2> Image2D; -typedef Image<3> Image3D; - /** @nosubgrouping @brief %Framebuffer diff --git a/src/Implementation/ShaderProgramState.h b/src/Implementation/ShaderProgramState.h index d81af0aca..3aeb48310 100644 --- a/src/Implementation/ShaderProgramState.h +++ b/src/Implementation/ShaderProgramState.h @@ -20,10 +20,11 @@ namespace Magnum { namespace Implementation { struct ShaderProgramState { - inline constexpr ShaderProgramState(): current(0) {} + inline constexpr ShaderProgramState(): current(0), maxSupportedVertexAttributeCount(0) {} /* Currently used program */ GLuint current; + GLint maxSupportedVertexAttributeCount; }; }} diff --git a/src/IndexedMesh.cpp b/src/IndexedMesh.cpp index e91453f74..b64885fae 100644 --- a/src/IndexedMesh.cpp +++ b/src/IndexedMesh.cpp @@ -33,6 +33,8 @@ IndexedMesh* IndexedMesh::setIndexBuffer(Buffer* buffer) { } void IndexedMesh::draw() { + if(!_indexCount) return; + bind(); /** @todo Start at given index */ @@ -42,7 +44,7 @@ void IndexedMesh::draw() { } void IndexedMesh::bind() { - CORRADE_ASSERT(_indexCount, "IndexedMesh: the mesh has zero index count!", ); + CORRADE_ASSERT(!_indexCount || _indexBuffer, "IndexedMesh: index buffer must be added if index count is non-zero", ); Mesh::bind(); (this->*bindIndexedImplementation)(); @@ -66,11 +68,13 @@ void IndexedMesh::bindIndexBufferImplementationDefault() {} void IndexedMesh::bindIndexBufferImplementationVAO() { bindVAO(vao); - _indexBuffer->bind(Buffer::Target::ElementArray); + if(_indexBuffer) _indexBuffer->bind(Buffer::Target::ElementArray); + else Buffer::unbind(Buffer::Target::ElementArray); } void IndexedMesh::bindIndexedImplementationDefault() { - _indexBuffer->bind(Buffer::Target::ElementArray); + if(_indexBuffer) _indexBuffer->bind(Buffer::Target::ElementArray); + else Buffer::unbind(Buffer::Target::ElementArray); } void IndexedMesh::bindIndexedImplementationVAO() {} diff --git a/src/IndexedMesh.h b/src/IndexedMesh.h index 1a0b25e9f..bac40636e 100644 --- a/src/IndexedMesh.h +++ b/src/IndexedMesh.h @@ -68,6 +68,9 @@ class MAGNUM_EXPORT IndexedMesh: public Mesh { /** * @brief Set index buffer * + * By default there is no index buffer. Parameter @p buffer can be + * `nullptr`, in that case current index buffer is unbound from the + * mesh. * @see MeshTools::compressIndices(), @fn_gl{BindVertexArray}, * @fn_gl{BindBuffer} (if @extension{APPLE,vertex_array_object} * is available) @@ -81,6 +84,7 @@ class MAGNUM_EXPORT IndexedMesh: public Mesh { * @brief Set index count * @return Pointer to self (for method chaining) * + * Default is zero. * @see MeshTools::compressIndices() */ inline IndexedMesh* setIndexCount(GLsizei count) { @@ -95,6 +99,7 @@ class MAGNUM_EXPORT IndexedMesh: public Mesh { * @brief Set index type * @return Pointer to self (for method chaining) * + * Default is @ref Type "Type::UnsignedShort". * @see MeshTools::compressIndices() */ inline IndexedMesh* setIndexType(Type type) { @@ -113,7 +118,31 @@ class MAGNUM_EXPORT IndexedMesh: public Mesh { * or @fn_gl{BindVertexArray} (if @extension{APPLE,vertex_array_object} * is available), @fn_gl{DrawElements} */ - void draw(); + void draw() override; + + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + inline IndexedMesh* setPrimitive(Primitive primitive) { + Mesh::setPrimitive(primitive); + return this; + } + inline IndexedMesh* setVertexCount(GLsizei vertexCount) { + Mesh::setVertexCount(vertexCount); + return this; + } + template inline IndexedMesh* addVertexBuffer(Buffer* buffer, const T&... attributes) { + Mesh::addVertexBuffer(buffer, attributes...); + return this; + } + template inline IndexedMesh* addInterleavedVertexBuffer(Buffer* buffer, GLintptr offset, const T&... attributes) { + Mesh::addInterleavedVertexBuffer(buffer, offset, attributes...); + return this; + } + template inline IndexedMesh* addVertexBufferStride(Buffer* buffer, GLintptr offset, GLsizei stride, const AbstractShaderProgram::Attribute& attribute) { + Mesh::addVertexBufferStride(buffer, offset, stride, attribute); + return this; + } + #endif private: static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context); diff --git a/src/Magnum.h b/src/Magnum.h index 6c757988b..75f5978b9 100644 --- a/src/Magnum.h +++ b/src/Magnum.h @@ -16,9 +16,11 @@ */ /** @file - * @brief Basic definitions + * @brief Basic definitions and forward declarations for Magnum namespace */ +#include + #include "magnumCompatibility.h" #include "magnumConfigure.h" @@ -95,6 +97,71 @@ typedef Math::Matrix4 Matrix4; using Math::deg; using Math::rad; +/* Forward declarations for all types in root namespace */ +class AbstractImage; +class AbstractShaderProgram; +class AbstractTexture; +class Buffer; + +#ifndef MAGNUM_TARGET_GLES2 +template class BufferedImage; +typedef BufferedImage<1> BufferedImage1D; +typedef BufferedImage<2> BufferedImage2D; +typedef BufferedImage<3> BufferedImage3D; +#endif + +#ifndef MAGNUM_TARGET_GLES +class BufferedTexture; +#endif + +template class Color3; +template class Color4; + +enum class Version: GLint; +class Context; +class Extension; + +class CubeMapTexture; + +#ifndef MAGNUM_TARGET_GLES +class CubeMapTextureArray; +#endif + +class Framebuffer; + +template class Image; +typedef Image<1> Image1D; +typedef Image<2> Image2D; +typedef Image<3> Image3D; + +template class ImageWrapper; +typedef ImageWrapper<1> ImageWrapper1D; +typedef ImageWrapper<2> ImageWrapper2D; +typedef ImageWrapper<3> ImageWrapper3D; + +class IndexedMesh; +class Mesh; +class Profiler; +class Query; +class Renderbuffer; + +enum class ResourceState: std::uint8_t; +enum class ResourceDataState: std::uint8_t; +enum class ResourcePolicy: std::uint8_t; +template class Resource; +template class ResourceManager; + +class Shader; + +template class Texture; +#ifndef MAGNUM_TARGET_GLES +typedef Texture<1> Texture1D; +#endif +typedef Texture<2> Texture2D; +typedef Texture<3> Texture3D; + +class Timeline; + } #endif diff --git a/src/Math/Vector2.h b/src/Math/Vector2.h index c4d26eb11..25361ea73 100644 --- a/src/Math/Vector2.h +++ b/src/Math/Vector2.h @@ -33,7 +33,7 @@ See @ref matrix-vector for brief introduction. template class Vector2: public Vector<2, T> { public: /** - * @brief %Vector in direction of X axis + * @brief %Vector in direction of X axis (right) * * Usable for translation in given axis, for example: * @code @@ -44,7 +44,7 @@ template class Vector2: public Vector<2, T> { inline constexpr static Vector2 xAxis(T length = T(1)) { return Vector2(length, T()); } /** - * @brief %Vector in direction of Y axis + * @brief %Vector in direction of Y axis (up) * * See xAxis() for more information. * @see yScale() @@ -52,7 +52,7 @@ template class Vector2: public Vector<2, T> { inline constexpr static Vector2 yAxis(T length = T(1)) { return Vector2(T(), length); } /** - * @brief Scaling vector in direction of X axis + * @brief Scaling vector in direction of X axis (width) * * Usable for scaling along given direction, for example: * @code @@ -63,7 +63,7 @@ template class Vector2: public Vector<2, T> { inline constexpr static Vector2 xScale(T scale) { return Vector2(scale, T(1)); } /** - * @brief Scaling vector in direction of Y axis + * @brief Scaling vector in direction of Y axis (height) * * See xScale() for more information. * @see yAxis() @@ -81,8 +81,8 @@ template class Vector2: public Vector<2, T> { /** * @brief Constructor - * @param x X value - * @param y Y value + * @param x X component + * @param y Y component */ inline constexpr Vector2(T x, T y): Vector<2, T>(x, y) {} diff --git a/src/Math/Vector3.h b/src/Math/Vector3.h index 51ce88517..f0668a352 100644 --- a/src/Math/Vector3.h +++ b/src/Math/Vector3.h @@ -34,7 +34,7 @@ homogeneous two-dimensional coordinates. template class Vector3: public Vector<3, T> { public: /** - * @brief %Vector in direction of X axis + * @brief %Vector in direction of X axis (right) * * Usable for translation or rotation along given axis, for example: * @code @@ -46,7 +46,7 @@ template class Vector3: public Vector<3, T> { inline constexpr static Vector3 xAxis(T length = T(1)) { return Vector3(length, T(), T()); } /** - * @brief %Vector in direction of Y axis + * @brief %Vector in direction of Y axis (up) * * See xAxis() for more information. * @see yScale() @@ -54,7 +54,7 @@ template class Vector3: public Vector<3, T> { inline constexpr static Vector3 yAxis(T length = T(1)) { return Vector3(T(), length, T()); } /** - * @brief %Vector in direction of Z axis + * @brief %Vector in direction of Z axis (backward) * * See xAxis() for more information. * @see zScale() @@ -62,7 +62,7 @@ template class Vector3: public Vector<3, T> { inline constexpr static Vector3 zAxis(T length = T(1)) { return Vector3(T(), T(), length); } /** - * @brief Scaling vector in direction of X axis + * @brief Scaling vector in direction of X axis (width) * * Usable for scaling along given direction, for example: * @code @@ -73,7 +73,7 @@ template class Vector3: public Vector<3, T> { inline constexpr static Vector3 xScale(T scale) { return Vector3(scale, T(1), T(1)); } /** - * @brief Scaling vector in direction of Y axis + * @brief Scaling vector in direction of Y axis (height) * * See xScale() for more information. * @see yAxis() @@ -81,7 +81,7 @@ template class Vector3: public Vector<3, T> { inline constexpr static Vector3 yScale(T scale) { return Vector3(T(1), scale, T(1)); } /** - * @brief Scaling vector in direction of Z axis + * @brief Scaling vector in direction of Z axis (depth) * * See xScale() for more information. * @see zAxis() diff --git a/src/Mesh.cpp b/src/Mesh.cpp index c39cd5d46..a979a9a9c 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -90,6 +90,8 @@ Mesh* Mesh::setVertexCount(GLsizei vertexCount) { } void Mesh::draw() { + if(!_vertexCount) return; + bind(); /** @todo Start at given index */ diff --git a/src/Mesh.h b/src/Mesh.h index dc8737ab4..b5357a536 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -27,9 +27,6 @@ namespace Magnum { -class Buffer; -class Context; - /** @brief Non-indexed mesh @@ -115,6 +112,8 @@ more information. @todo Support for indirect draw buffer (OpenGL 4.0, @extension{ARB,draw_indirect}) @todo Redo in a way that allows glMultiDrawArrays, glDrawArraysInstanced etc. +@todo Allow unbinding all vertex buffers with some function (not as side effect), + similarly to unbinding index buffer in IndexedMesh */ class MAGNUM_EXPORT Mesh { friend class IndexedMesh; @@ -388,6 +387,8 @@ class MAGNUM_EXPORT Mesh { /** * @brief Set primitive type * @return Pointer to self (for method chaining) + * + * Default is @ref Primitive "Primitive::Triangles". */ inline Mesh* setPrimitive(Primitive primitive) { _primitive = primitive; @@ -401,6 +402,7 @@ class MAGNUM_EXPORT Mesh { * @brief Set vertex count * @return Pointer to self (for method chaining) * + * Default is zero. * @attention All bound attributes are reset after calling this * function, so you must call * addVertexBuffer()/addInterleavedVertexBuffer() afterwards. diff --git a/src/MeshTools/CompressIndices.h b/src/MeshTools/CompressIndices.h index 1ca638eba..e9bf40c9e 100644 --- a/src/MeshTools/CompressIndices.h +++ b/src/MeshTools/CompressIndices.h @@ -26,11 +26,7 @@ #include "magnumMeshToolsVisibility.h" -namespace Magnum { - -class IndexedMesh; - -namespace MeshTools { +namespace Magnum { namespace MeshTools { #ifndef DOXYGEN_GENERATING_OUTPUT namespace Implementation { diff --git a/src/Platform/GlutApplication.h b/src/Platform/GlutApplication.h index caf34fb17..56f0ff885 100644 --- a/src/Platform/GlutApplication.h +++ b/src/Platform/GlutApplication.h @@ -83,8 +83,8 @@ class GlutApplication { * @brief Viewport event * * Called when viewport size changes. You should pass the new size to - * Framebuffer::setViewport() or SceneGraph::Camera::setViewport(), - * if using scene graph. + * Framebuffer::setViewport() (and SceneGraph::AbstractCamera::setViewport(), + * if using scene graph). */ virtual void viewportEvent(const Math::Vector2& size) = 0; @@ -92,7 +92,7 @@ class GlutApplication { * @brief Draw event * * Here implement your drawing functions, such as calling - * SceneGraph::Camera::draw(). After drawing is finished, call + * SceneGraph::AbstractCamera::draw(). After drawing is finished, call * swapBuffers(). If you want to draw immediately again, call also * redraw(). */ @@ -110,7 +110,7 @@ class GlutApplication { /** * @brief Redraw immediately * - * Marks the window for redrawing, resulting in call of drawEvent() + * Marks the window for redrawing, resulting in call to drawEvent() * in the next iteration. */ virtual inline void redraw() { @@ -230,7 +230,6 @@ class GlutApplication { * * Called when any mouse button is pressed and mouse is moved. Default * implementation does nothing. - * * @see setMouseTracking() */ virtual void mouseMotionEvent(const Math::Vector2& position); diff --git a/src/Platform/NaClApplication.cpp b/src/Platform/NaClApplication.cpp index 9db9afa6b..c8af5f34e 100644 --- a/src/Platform/NaClApplication.cpp +++ b/src/Platform/NaClApplication.cpp @@ -83,15 +83,33 @@ bool NaClApplication::HandleInputEvent(const pp::InputEvent& event) { CORRADE_INTERNAL_ASSERT(!(flags & Flag::SwapInProgress)); switch(event.GetType()) { - case PP_INPUTEVENT_TYPE_KEYDOWN: { + case PP_INPUTEVENT_TYPE_KEYDOWN: + case PP_INPUTEVENT_TYPE_KEYUP: { pp::KeyboardInputEvent keyEvent(event); - keyPressEvent(static_cast(keyEvent.GetKeyCode()), static_cast(keyEvent.GetModifiers()), {}); + KeyEvent e(static_cast(keyEvent.GetKeyCode()), static_cast(keyEvent.GetModifiers())); + event.GetType() == PP_INPUTEVENT_TYPE_KEYDOWN ? keyPressEvent(e) : keyReleaseEvent(e); + if(!e.isAccepted()) return false; break; - } case PP_INPUTEVENT_TYPE_KEYUP: { - pp::KeyboardInputEvent keyEvent(event); - keyReleaseEvent(static_cast(keyEvent.GetKeyCode()), static_cast(keyEvent.GetModifiers()), {}); + } + + case PP_INPUTEVENT_TYPE_MOUSEDOWN: + case PP_INPUTEVENT_TYPE_MOUSEUP: { + pp::MouseInputEvent mouseEvent(event); + MouseEvent e(static_cast(mouseEvent.GetButton()), {mouseEvent.GetPosition().x(), mouseEvent.GetPosition().y()}, static_cast(mouseEvent.GetModifiers())); + event.GetType() == PP_INPUTEVENT_TYPE_MOUSEDOWN ? mousePressEvent(e) : mouseReleaseEvent(e); + if(!e.isAccepted()) return false; + break; + } + + case PP_INPUTEVENT_TYPE_MOUSEMOVE: { + pp::MouseInputEvent mouseEvent(event); + MouseMoveEvent e({mouseEvent.GetPosition().x(), mouseEvent.GetPosition().y()}, static_cast(mouseEvent.GetModifiers())); + mouseMoveEvent(e); + if(!e.isAccepted()) return false; break; - } default: return false; + } + + default: return false; } /* Not need to redraw => assume the event was ignored */ diff --git a/src/Platform/NaClApplication.h b/src/Platform/NaClApplication.h index 69f64d140..a064b2581 100644 --- a/src/Platform/NaClApplication.h +++ b/src/Platform/NaClApplication.h @@ -46,6 +46,9 @@ namespace Platform { /** @nosubgrouping @brief NaCl application +Application running in [Google Chrome Native Client](https://developers.google.com/native-client/). +Supports keyboard and mouse handling. + @section NaClApplication-usage Usage You need to implement at least drawEvent() and viewportEvent() to be able to @@ -60,6 +63,11 @@ MAGNUM_NACLAPPLICATION_MAIN(MyApplication) */ class NaClApplication: public pp::Instance, public pp::Graphics3DClient { public: + class InputEvent; + class KeyEvent; + class MouseEvent; + class MouseMoveEvent; + /** * @brief Constructor * @param instance Module instance @@ -71,53 +79,123 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient { ~NaClApplication(); + protected: + /** @{ @name Drawing functions */ - protected: + /** @copydoc GlutApplication::viewportEvent() */ + virtual void viewportEvent(const Math::Vector2& size) = 0; + + /** @copydoc GlutApplication::drawEvent() */ + virtual void drawEvent() = 0; + + /** @copydoc GlutApplication::swapBuffers() */ + void swapBuffers(); + + /** @copydoc GlutApplication::redraw() */ + inline void redraw() { flags |= Flag::Redraw; } + + /*@}*/ + + /** @{ @name Keyboard handling */ + /** - * @brief Viewport event + * @brief Key press event * - * Called when viewport size changes. You should pass the new size to - * Framebuffer::setViewport() or SceneGraph::Camera::setViewport(), - * if using scene graph. + * Called when an key is pressed. Default implementation does nothing. + * If you accept the event, call @ref InputEvent::setAccepted() "setAccepted()" + * on it, otherwise the event will be propagated to the browser. */ - virtual void viewportEvent(const Math::Vector2& size) = 0; + virtual void keyPressEvent(KeyEvent& event); /** - * @brief Draw event + * @brief Key release event * - * Here implement your drawing functions, such as calling - * SceneGraph::Camera::draw(). After drawing is finished, call - * swapBuffers(). If you want to draw immediately again, call also - * redraw(). + * Called when an key is released. Default implementation does nothing. + * If you accept the event, call @ref InputEvent::setAccepted() "setAccepted()" + * on it, otherwise the event will be propagated to the browser. */ - virtual void drawEvent() = 0; + virtual void keyReleaseEvent(KeyEvent& event); + + /*@}*/ + + /** @{ @name Mouse handling */ /** - * @brief Swap buffers + * @brief Mouse press event * - * Paints currently rendered framebuffer on screen. + * Called when mouse button is pressed. Default implementation does + * nothing. If you accept the event, call @ref InputEvent::setAccepted() "setAccepted()" + * on it, otherwise the event will be propagated to the browser. */ - void swapBuffers(); + virtual void mousePressEvent(MouseEvent& event); /** - * @brief Redraw immediately + * @brief Mouse release event * - * Marks the window for redrawing, resulting in call of drawEvent() - * in the next iteration. + * Called when mouse button is released. Default implementation does + * nothing. If you accept the event, call @ref InputEvent::setAccepted() "setAccepted()" + * on it, otherwise the event will be propagated to the browser. */ - inline void redraw() { flags |= Flag::Redraw; } + virtual void mouseReleaseEvent(MouseEvent& event); + + /** + * @brief Mouse move event + * + * Called when mouse is moved. Default implementation does nothing. If + * you accept the event, call @ref InputEvent::setAccepted() "setAccepted()" + * on it, otherwise the event will be propagated to the browser. + */ + virtual void mouseMoveEvent(MouseMoveEvent& event); /*@}*/ - /** @{ @name Keyboard handling */ + private: + enum class Flag: std::uint8_t { + ViewportUpdated = 1 << 0, + SwapInProgress = 1 << 1, + Redraw = 1 << 2 + }; + typedef Corrade::Containers::EnumSet Flags; + + inline void Graphics3DContextLost() override { + CORRADE_ASSERT(false, "NaClApplication: context unexpectedly lost", ); + } + + void DidChangeView(const pp::View& view) override; + + bool HandleInputEvent(const pp::InputEvent& event) override; + + static void swapCallback(void* applicationInstance, std::int32_t); + + pp::Graphics3D* graphics; + Context* c; + Math::Vector2 viewportSize; + Flags flags; + + CORRADE_ENUMSET_FRIEND_OPERATORS(Flags) +}; + +/** +@brief Base for input events + +If you accept the event, call setAccepted(), otherwise the event will be +propagated to the browser. +@see KeyEvent, MouseEvent, MouseMoveEvent, keyPressEvent(), keyReleaseEvent(), + mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent() +*/ +class NaClApplication::InputEvent { + InputEvent(const InputEvent& other) = delete; + InputEvent(InputEvent&& other) = delete; + InputEvent& operator=(const InputEvent& other) = delete; + InputEvent& operator=(InputEvent&& other) = delete; public: /** * @brief %Modifier * * @todo AltGr + PP_INPUTEVENT_MODIFIER_ISKEYPAD, PP_INPUTEVENT_MODIFIER_ISAUTOREPEAT - * @see Modifiers, keyPressEvent(), keyReleaseEvent() + * @see Modifiers, modifiers() */ enum class Modifier: std::uint32_t { Shift = PP_INPUTEVENT_MODIFIER_SHIFTKEY, /**< Shift */ @@ -136,15 +214,51 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient { /** * @brief Set of modifiers * - * @see keyPressEvent(), keyReleaseEvent() + * @see modifiers() */ typedef Corrade::Containers::EnumSet Modifiers; + inline virtual ~InputEvent() {} + + /** @brief Modifiers */ + inline Modifiers modifiers() const { return _modifiers; } + + /** + * @brief Set event as accepted + * + * If the event is ignored (i.e., not set as accepted), it is + * propagated to the browser. By default is each event ignored. + */ + inline void setAccepted(bool accepted = true) { _accepted = accepted; } + + /** @brief Whether the event is accepted */ + inline bool isAccepted() { return _accepted; } + + #ifndef DOXYGEN_GENERATING_OUTPUT + protected: + inline InputEvent(Modifiers modifiers): _accepted(false), _modifiers(modifiers) {} + #endif + + private: + bool _accepted; + const Modifiers _modifiers; +}; + +/** +@brief Key event + +See InputEvent for more information. +@see keyPressEvent(), keyReleaseEvent() +*/ +class NaClApplication::KeyEvent: public NaClApplication::InputEvent { + friend class NaClApplication; + + public: /** * @brief Key * * @todo Slash, percent, equal to be compatible with *XApplication - * @see keyPressEvent(), keyReleaseEvent() + * @see key() */ enum class Key: std::uint32_t { Enter = 0x0D, /**< Enter */ @@ -216,51 +330,66 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient { Z = 'Z' /**< Letter Z */ }; - protected: + /** @brief Key */ + inline Key key() const { return _key; } + + private: + inline KeyEvent(Key key, Modifiers modifiers): InputEvent(modifiers), _key(key) {} + + const Key _key; +}; + +/** +@brief Mouse event + +See InputEvent for more information. +@see MouseMoveEvent, mousePressEvent(), mouseReleaseEvent() +*/ +class NaClApplication::MouseEvent: public NaClApplication::InputEvent { + friend class NaClApplication; + + public: /** - * @brief Key press event - * @param key Key pressed - * @param modifiers Active modifiers - * @param position Cursor position (not implemented) + * @brief Button * - * Called when an key is pressed. Default implementation does nothing. + * @see button() */ - virtual void keyPressEvent(Key key, Modifiers modifiers, const Math::Vector2& position); + enum class Button: unsigned int { + Left = PP_INPUTEVENT_MOUSEBUTTON_LEFT, /**< Left button */ + Middle = PP_INPUTEVENT_MOUSEBUTTON_MIDDLE, /**< Middle button */ + Right = PP_INPUTEVENT_MOUSEBUTTON_RIGHT /**< Right button */ + }; - /** - * @brief Key release event - * @param key Key released - * @param modifiers Active modifiers - * @param position Cursor position (not implemented) - */ - virtual void keyReleaseEvent(Key key, Modifiers modifiers, const Math::Vector2& position); + /** @brief Button */ + inline Button button() const { return _button; } - /*@}*/ + /** @brief Position */ + inline Math::Vector2 position() const { return _position; } private: - enum class Flag: std::uint8_t { - ViewportUpdated = 1 << 0, - SwapInProgress = 1 << 1, - Redraw = 1 << 2 - }; - typedef Corrade::Containers::EnumSet Flags; + inline MouseEvent(Button button, const Math::Vector2& position, Modifiers modifiers): InputEvent(modifiers), _button(button), _position(position) {} - inline void Graphics3DContextLost() override { - CORRADE_ASSERT(false, "NaClApplication: context unexpectedly lost", ); - } + const Button _button; + const Math::Vector2 _position; +}; - void DidChangeView(const pp::View& view) override; +/** +@brief Mouse move event - bool HandleInputEvent(const pp::InputEvent& event) override; +See InputEvent for more information. +@see MouseEvent, mouseMoveEvent() +*/ +class NaClApplication::MouseMoveEvent: public NaClApplication::InputEvent { + friend class NaClApplication; - static void swapCallback(void* applicationInstance, std::int32_t); + public: + /** @brief Position */ + inline Math::Vector2 position() const { return _position; } - pp::Graphics3D* graphics; - Context* c; - Math::Vector2 viewportSize; - Flags flags; + private: + inline MouseMoveEvent(const Math::Vector2& position, Modifiers modifiers): InputEvent(modifiers), _position(position) {} - CORRADE_ENUMSET_FRIEND_OPERATORS(Flags) + const Math::Vector2 _position; }; CORRADE_ENUMSET_OPERATORS(NaClApplication::Flags) @@ -308,9 +437,14 @@ When no other application header is included this macro is also aliased to #endif #endif +CORRADE_ENUMSET_OPERATORS(NaClApplication::InputEvent::Modifiers) + /* Implementations for inline functions with unused parameters */ -inline void NaClApplication::keyPressEvent(Key, Modifiers, const Math::Vector2&) {} -inline void NaClApplication::keyReleaseEvent(Key, Modifiers, const Math::Vector2&) {} +inline void NaClApplication::keyPressEvent(KeyEvent&) {} +inline void NaClApplication::keyReleaseEvent(KeyEvent&) {} +inline void NaClApplication::mousePressEvent(MouseEvent&) {} +inline void NaClApplication::mouseReleaseEvent(MouseEvent&) {} +inline void NaClApplication::mouseMoveEvent(MouseMoveEvent&) {} }} diff --git a/src/Platform/Sdl2Application.cpp b/src/Platform/Sdl2Application.cpp index 4f6091493..00d40aca8 100644 --- a/src/Platform/Sdl2Application.cpp +++ b/src/Platform/Sdl2Application.cpp @@ -82,6 +82,7 @@ int Sdl2Application::exec() { _redraw = true; break; } break; + case SDL_KEYDOWN: case SDL_KEYUP: { /* @@ -92,31 +93,36 @@ int Sdl2Application::exec() { * right were pressed, which is usually not what the * developers wants. */ - Modifiers modifiers(static_cast(event.key.keysym.mod)); - if(modifiers & Modifier::Shift) modifiers |= Modifier::Shift; - if(modifiers & Modifier::Ctrl) modifiers |= Modifier::Ctrl; - if(modifiers & Modifier::Alt) modifiers |= Modifier::Alt; - - if(event.type == SDL_KEYDOWN) - keyPressEvent(static_cast(event.key.keysym.sym), modifiers, {}); - else - keyReleaseEvent(static_cast(event.key.keysym.sym), modifiers, {}); - break; - } case SDL_MOUSEBUTTONDOWN: - mousePressEvent(static_cast(event.button.button), Modifiers(), {event.button.x, event.button.y}); + InputEvent::Modifiers modifiers(static_cast(event.key.keysym.mod)); + if(modifiers & InputEvent::Modifier::Shift) modifiers |= InputEvent::Modifier::Shift; + if(modifiers & InputEvent::Modifier::Ctrl) modifiers |= InputEvent::Modifier::Ctrl; + if(modifiers & InputEvent::Modifier::Alt) modifiers |= InputEvent::Modifier::Alt; + + KeyEvent e(static_cast(event.key.keysym.sym), modifiers); + event.type == SDL_KEYDOWN ? keyPressEvent(e) : keyReleaseEvent(e); break; - case SDL_MOUSEBUTTONUP: - mouseReleaseEvent(static_cast(event.button.button), Modifiers(), {event.button.x, event.button.y}); + } + + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: { + MouseEvent e(static_cast(event.button.button), {event.button.x, event.button.y}); + event.type == SDL_MOUSEBUTTONDOWN ? mousePressEvent(e) : mouseReleaseEvent(e); break; + } + case SDL_MOUSEWHEEL: - if(event.wheel.y != 0) - mousePressEvent(event.wheel.y < 0 ? MouseButton::WheelUp : MouseButton::WheelDown, Modifiers(), {event.wheel.x, event.wheel.y}); - break; - case SDL_MOUSEMOTION: - mouseMotionEvent(Modifiers(), {event.motion.x, event.motion.y}); + if(event.wheel.y != 0) { + MouseEvent e(event.wheel.y < 0 ? MouseEvent::Button::WheelUp : MouseEvent::Button::WheelDown, {event.wheel.x, event.wheel.y}); + mousePressEvent(e); + } break; + + case SDL_MOUSEMOTION: { + MouseMoveEvent e({event.motion.x, event.motion.y}); + mouseMoveEvent(e); break; - case SDL_QUIT: - return 0; + } + + case SDL_QUIT: return 0; } } diff --git a/src/Platform/Sdl2Application.h b/src/Platform/Sdl2Application.h index 59b978420..3984f41da 100644 --- a/src/Platform/Sdl2Application.h +++ b/src/Platform/Sdl2Application.h @@ -37,7 +37,8 @@ namespace Platform { /** @nosubgrouping @brief SDL2 application -Supports keyboard and mouse handling. +Application using [Simple DirectMedia Layer](www.libsdl.org/). Supports +keyboard and mouse handling. @section Sdl2Application-usage Usage @@ -53,6 +54,11 @@ MAGNUM_SDL2APPLICATION_MAIN(MyApplication) */ class Sdl2Application { public: + class InputEvent; + class KeyEvent; + class MouseEvent; + class MouseMoveEvent; + /** * @brief Constructor * @param argc Count of arguments of `main()` function @@ -78,9 +84,10 @@ class Sdl2Application { */ int exec(); + protected: + /** @{ @name Drawing functions */ - protected: /** @copydoc GlutApplication::viewportEvent() */ virtual void viewportEvent(const Math::Vector2& size) = 0; @@ -97,11 +104,75 @@ class Sdl2Application { /** @{ @name Keyboard handling */ + /** + * @brief Key press event + * + * Called when an key is pressed. Default implementation does nothing. + */ + virtual void keyPressEvent(KeyEvent& event); + + /** + * @brief Key release event + * + * Called when an key is released. Default implementation does nothing. + */ + virtual void keyReleaseEvent(KeyEvent& event); + + /*@}*/ + + /** @{ @name Mouse handling */ + + /** + * @brief Mouse press event + * + * Called when mouse button is pressed. Default implementation does + * nothing. + */ + virtual void mousePressEvent(MouseEvent& event); + + /** + * @brief Mouse release event + * + * Called when mouse button is released. Default implementation does + * nothing. + */ + virtual void mouseReleaseEvent(MouseEvent& event); + + /** + * @brief Mouse move event + * + * Called when mouse is moved. Default implementation does nothing. + */ + virtual void mouseMoveEvent(MouseMoveEvent& event); + + /*@}*/ + + private: + SDL_Window* window; + SDL_GLContext context; + + Context* c; + + bool _redraw; +}; + +/** +@brief Base for input events + +@see KeyEvent, MouseEvent, MouseMoveEvent, keyPressEvent(), keyReleaseEvent(), + mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent() +*/ +class Sdl2Application::InputEvent { + InputEvent(const InputEvent& other) = delete; + InputEvent(InputEvent&& other) = delete; + InputEvent& operator=(const InputEvent& other) = delete; + InputEvent& operator=(InputEvent&& other) = delete; + public: /** * @brief %Modifier * - * @see Modifiers, keyPressEvent(), keyReleaseEvent() + * @see Modifiers, KeyEvent::modifiers() */ enum class Modifier: Uint16 { Shift = KMOD_SHIFT, /**< Shift */ @@ -116,14 +187,47 @@ class Sdl2Application { /** * @brief Set of modifiers * - * @see keyPressEvent(), keyReleaseEvent() + * @see KeyEvent::modifiers() */ typedef Corrade::Containers::EnumSet Modifiers; + inline virtual ~InputEvent() {} + + /** + * @brief Set event as accepted + * + * Does nothing. Included only for compatibility with + * NaClApplication::InputEvent. + */ + inline void setAccepted(bool = true) {} + + /** + * @brief Whether the event is accepted + * + * Always returns true. Included only for compatibility with + * NaClApplication::InputEvent. + */ + inline bool isAccepted() const { return true; } + + #ifndef DOXYGEN_GENERATING_OUTPUT + protected: + inline InputEvent() {} + #endif +}; + +/** +@brief Key event + +@see keyPressEvent(), keyReleaseEvent() +*/ +class Sdl2Application::KeyEvent: public Sdl2Application::InputEvent { + friend class Sdl2Application; + + public: /** * @brief Key * - * @see keyPressEvent(), keyReleaseEvent() + * @see key() */ enum class Key: SDL_Keycode { Enter = SDLK_RETURN, /**< Enter */ @@ -198,34 +302,34 @@ class Sdl2Application { Z = SDLK_z /**< Letter Z */ }; - protected: - /** - * @brief Key press event - * @param key Key pressed - * @param modifiers Active modifiers - * @param position Cursor position (not implemented) - */ - virtual void keyPressEvent(Key key, Modifiers modifiers, const Math::Vector2& position); + /** @brief Key */ + inline Key key() const { return _key; } - /** - * @brief Key release event - * @param key Key released - * @param modifiers Active modifiers - * @param position Cursor position (not implemented) - */ - virtual void keyReleaseEvent(Key key, Modifiers modifiers, const Math::Vector2& position); + /** @brief Modifiers */ + inline Modifiers modifiers() const { return _modifiers; } - /*@}*/ + private: + inline KeyEvent(Key key, Modifiers modifiers): _key(key), _modifiers(modifiers) {} - /** @{ @name Mouse handling */ + const Key _key; + const Modifiers _modifiers; +}; + +/** +@brief Mouse event + +@see MouseMoveEvent, mousePressEvent(), mouseReleaseEvent() +*/ +class Sdl2Application::MouseEvent: public Sdl2Application::InputEvent { + friend class Sdl2Application; public: /** * @brief Mouse button * - * @see mouseEvent() + * @see button() */ - enum class MouseButton: Uint8 { + enum class Button: Uint8 { Left = SDL_BUTTON_LEFT, /**< Left button */ Middle = SDL_BUTTON_MIDDLE, /**< Middle button */ Right = SDL_BUTTON_RIGHT, /**< Right button */ @@ -233,57 +337,35 @@ class Sdl2Application { WheelDown = 5 /**< Wheel down */ }; - /** - * @brief Mouse state - * - * @see mouseEvent() - */ - enum class MouseState: Uint8 { - Pressed = SDL_PRESSED, /**< Button pressed */ - Released = SDL_RELEASED /**< Button released */ - }; + /** @brief Button */ + inline Button button() const { return _button; } - protected: - /** - * @brief Mouse press event - * @param button Button pressed - * @param modifiers Active modifiers (not implemented) - * @param position Cursor position - * - * Called when mouse button is pressed. Default implementation does - * nothing. - */ - virtual void mousePressEvent(MouseButton button, Modifiers modifiers, const Math::Vector2& position); + /** @brief Position */ + inline Math::Vector2 position() const { return _position; } - /** - * @brief Mouse release event - * @param button Button released - * @param modifiers Active modifiers (not implemented) - * @param position Cursor position - * - * Called when mouse button is released. Default implementation does - * nothing. - */ - virtual void mouseReleaseEvent(MouseButton button, Modifiers modifiers, const Math::Vector2& position); + private: + inline MouseEvent(Button button, const Math::Vector2& position): _button(button), _position(position) {} - /** - * @brief Mouse motion event - * @param modifiers Active modifiers (not implemented) - * @param position Mouse position relative to the window - * - * Called when mouse is moved. Default implementation does nothing. - */ - virtual void mouseMotionEvent(Modifiers modifiers, const Math::Vector2& position); + const Button _button; + const Math::Vector2 _position; +}; - /*@}*/ +/** +@brief Mouse move event - private: - SDL_Window* window; - SDL_GLContext context; +@see MouseEvent, mouseMoveEvent() +*/ +class Sdl2Application::MouseMoveEvent: public Sdl2Application::InputEvent { + friend class Sdl2Application; - Context* c; + public: + /** @brief Position */ + inline Math::Vector2 position() const { return _position; } - bool _redraw; + private: + inline MouseMoveEvent(const Math::Vector2& position): _position(position) {} + + const Math::Vector2 _position; }; /** @hideinitializer @@ -314,14 +396,14 @@ When no other application header is included this macro is also aliased to #endif #endif -CORRADE_ENUMSET_OPERATORS(Sdl2Application::Modifiers) +CORRADE_ENUMSET_OPERATORS(Sdl2Application::InputEvent::Modifiers) /* Implementations for inline functions with unused parameters */ -inline void Sdl2Application::keyPressEvent(Key, Modifiers, const Math::Vector2&) {} -inline void Sdl2Application::keyReleaseEvent(Key, Modifiers, const Math::Vector2&) {} -inline void Sdl2Application::mousePressEvent(MouseButton, Modifiers, const Math::Vector2&) {} -inline void Sdl2Application::mouseReleaseEvent(MouseButton, Modifiers, const Math::Vector2&) {} -inline void Sdl2Application::mouseMotionEvent(Modifiers, const Math::Vector2&) {} +inline void Sdl2Application::keyPressEvent(KeyEvent&) {} +inline void Sdl2Application::keyReleaseEvent(KeyEvent&) {} +inline void Sdl2Application::mousePressEvent(MouseEvent&) {} +inline void Sdl2Application::mouseReleaseEvent(MouseEvent&) {} +inline void Sdl2Application::mouseMoveEvent(MouseMoveEvent&) {} }} diff --git a/src/Primitives/Capsule.h b/src/Primitives/Capsule.h index 76dd89984..1d9e118a6 100644 --- a/src/Primitives/Capsule.h +++ b/src/Primitives/Capsule.h @@ -26,7 +26,7 @@ namespace Magnum { namespace Primitives { /** @brief 3D capsule primitive -Cylinder along Y axis with hemispheres instead of caps. Indexed triangle mesh +%Cylinder along Y axis with hemispheres instead of caps. Indexed triangle mesh with normals and optional 2D texture coordinates. */ class Capsule: public Trade::MeshData3D { diff --git a/src/ResourceManager.h b/src/ResourceManager.h index bd164e741..48835fffc 100644 --- a/src/ResourceManager.h +++ b/src/ResourceManager.h @@ -29,7 +29,7 @@ namespace Magnum { * * @see Resource::state(), ResourceManager::state() */ -enum class ResourceState { +enum class ResourceState: std::uint8_t { /** The resource is not yet loaded. */ NotLoaded, @@ -48,7 +48,7 @@ enum class ResourceState { * * @see ResourceManager::set() */ -enum class ResourceDataState { +enum class ResourceDataState: std::uint8_t { /** * The resource can be changed by the manager in the future. This is * slower, as Resource needs to ask the manager for new version every time @@ -70,7 +70,7 @@ enum class ResourceDataState { @see ResourceManager::set(), ResourceManager::free() */ -enum class ResourcePolicy { +enum class ResourcePolicy: std::uint8_t { /** The resource will stay resident for whole lifetime of resource manager. */ Resident, @@ -95,9 +95,10 @@ class ResourceKey: public Corrade::Utility::MurmurHash2::Digest { /** * @brief Default constructor * - * The same as calling other constructors with empty string. + * Creates zero key. Note that it is not the same as calling other + * constructors with empty string. */ - inline ResourceKey(): Corrade::Utility::MurmurHash2::Digest(Corrade::Utility::MurmurHash2()("")) {} + inline constexpr ResourceKey() {} /** @brief Constructor */ inline ResourceKey(const std::string& key): Corrade::Utility::MurmurHash2::Digest(Corrade::Utility::MurmurHash2()(key)) {} @@ -342,22 +343,30 @@ template class Resource { return data; } - /** @brief %Resource data */ - inline U& operator*() { + /** + * @brief %Resource data + * + * The resource must be loaded before accessing it. Use boolean + * conversion operator or state() for testing whether it is loaded. + */ + inline operator U*() { acquire(); - return *static_cast(data); + CORRADE_ASSERT(data, "Resource: accessing not loaded data with key" << key(), nullptr); + return static_cast(data); } - /** @brief %Resource data */ + /** @overload */ inline U* operator->() { acquire(); + CORRADE_ASSERT(data, "Resource: accessing not loaded data with key" << key(), nullptr); return static_cast(data); } - /** @brief %Resource data */ - inline operator U*() { + /** @overload */ + inline U& operator*() { acquire(); - return static_cast(data); + CORRADE_ASSERT(data, "Resource: accessing not loaded data with key" << key(), *static_cast(data)); + return *static_cast(data); } private: diff --git a/src/Shaders/CMakeLists.txt b/src/Shaders/CMakeLists.txt index 46139bbed..5ef7001c6 100644 --- a/src/Shaders/CMakeLists.txt +++ b/src/Shaders/CMakeLists.txt @@ -11,6 +11,7 @@ set(MagnumShaders_SRCS set(MagnumShaders_HEADERS FlatShader.h PhongShader.h + Shaders.h VertexColorShader.h magnumShadersVisibility.h) diff --git a/src/Shaders/Shaders.h b/src/Shaders/Shaders.h new file mode 100644 index 000000000..5a36b34f8 --- /dev/null +++ b/src/Shaders/Shaders.h @@ -0,0 +1,38 @@ +#ifndef Magnum_Shaders_Shader_h +#define Magnum_Shaders_Shader_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Forward declarations for Magnum::Shaders namespace + */ + +#include + +namespace Magnum { namespace Shaders { + +template class FlatShader; +typedef FlatShader<2> FlatShader2D; +typedef FlatShader<3> FlatShader3D; + +class PhongShader; + +template class VertexColorShader; +typedef VertexColorShader<2> VertexColorShader2D; +typedef VertexColorShader<3> VertexColorShader3D; + +}} + +#endif diff --git a/src/TypeTraits.h b/src/TypeTraits.h index 23f882df5..49e75e871 100644 --- a/src/TypeTraits.h +++ b/src/TypeTraits.h @@ -30,9 +30,6 @@ namespace Math { template class Vector; } -template class Color3; -template class Color4; - /** @brief Traits class for plain OpenGL types