From 1a729aa3af7030dd645feeb32fbd6081c5691613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 15 Nov 2012 21:59:36 +0100 Subject: [PATCH 01/13] NaClApplication: mouse input handling. --- src/Platform/NaClApplication.cpp | 12 +++++++ src/Platform/NaClApplication.h | 55 +++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/Platform/NaClApplication.cpp b/src/Platform/NaClApplication.cpp index 9db9afa6b..1c57c2f14 100644 --- a/src/Platform/NaClApplication.cpp +++ b/src/Platform/NaClApplication.cpp @@ -91,6 +91,18 @@ bool NaClApplication::HandleInputEvent(const pp::InputEvent& event) { pp::KeyboardInputEvent keyEvent(event); keyReleaseEvent(static_cast(keyEvent.GetKeyCode()), static_cast(keyEvent.GetModifiers()), {}); break; + } case PP_INPUTEVENT_TYPE_MOUSEDOWN: { + pp::MouseInputEvent mouseEvent(event); + mousePressEvent(static_cast(mouseEvent.GetButton()), static_cast(mouseEvent.GetModifiers()), {mouseEvent.GetPosition().x(), mouseEvent.GetPosition().y()}); + break; + } case PP_INPUTEVENT_TYPE_MOUSEUP: { + pp::MouseInputEvent mouseEvent(event); + mouseReleaseEvent(static_cast(mouseEvent.GetButton()), static_cast(mouseEvent.GetModifiers()), {mouseEvent.GetPosition().x(), mouseEvent.GetPosition().y()}); + break; + } case PP_INPUTEVENT_TYPE_MOUSEMOVE: { + pp::MouseInputEvent mouseEvent(event); + mouseMotionEvent(static_cast(mouseEvent.GetModifiers()), {mouseEvent.GetPosition().x(), mouseEvent.GetPosition().y()}); + break; } default: return false; } diff --git a/src/Platform/NaClApplication.h b/src/Platform/NaClApplication.h index 69f64d140..bb66000b5 100644 --- a/src/Platform/NaClApplication.h +++ b/src/Platform/NaClApplication.h @@ -136,7 +136,8 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient { /** * @brief Set of modifiers * - * @see keyPressEvent(), keyReleaseEvent() + * @see keyPressEvent(), keyReleaseEvent(), mousePressEvent(), + * mouseReleaseEvent(), mouseMotionEvent() */ typedef Corrade::Containers::EnumSet Modifiers; @@ -237,6 +238,54 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient { /*@}*/ + /** @{ @name Mouse handling */ + + public: + /** + * @brief Mouse button + * + * @see mousePressEvent(), mouseReleaseEvent() + */ + enum class MouseButton: unsigned int { + Left = PP_INPUTEVENT_MOUSEBUTTON_LEFT, /**< Left button */ + Middle = PP_INPUTEVENT_MOUSEBUTTON_MIDDLE, /**< Middle button */ + Right = PP_INPUTEVENT_MOUSEBUTTON_RIGHT /**< Right button */ + }; + + protected: + /** + * @brief Mouse press event + * @param button Button pressed + * @param modifiers Active modifiers + * @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 Mouse release event + * @param button Button released + * @param modifiers Active modifiers + * @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); + + /** + * @brief Mouse motion event + * @param modifiers Active modifiers + * @param position Cursor position + * + * Called when mouse is moved. + */ + virtual void mouseMotionEvent(Modifiers modifiers, const Math::Vector2& position); + + /*@}*/ + private: enum class Flag: std::uint8_t { ViewportUpdated = 1 << 0, @@ -311,6 +360,10 @@ When no other application header is included this macro is also aliased to /* 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::mousePressEvent(MouseButton, Modifiers, const Math::Vector2&) {} +inline void NaClApplication::mouseReleaseEvent(MouseButton, Modifiers, const Math::Vector2&) {} +inline void NaClApplication::mouseMotionEvent(Modifiers, const Math::Vector2&) {} + }} From a3c37cd277cda93eaac2a632c5e186d6d81b8d91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 15 Nov 2012 23:08:15 +0100 Subject: [PATCH 02/13] Doc++, minor cleanup. --- src/AbstractTexture.h | 7 ++++++- src/IndexedMesh.h | 2 ++ src/Math/Vector2.h | 12 +++++------ src/Math/Vector3.h | 12 +++++------ src/Mesh.h | 3 +++ src/MeshTools/CompressIndices.h | 6 +----- src/Platform/GlutApplication.h | 9 ++++----- src/Platform/NaClApplication.h | 36 +++++++++------------------------ src/Platform/Sdl2Application.h | 15 +++----------- src/Primitives/Capsule.h | 2 +- 10 files changed, 41 insertions(+), 63 deletions(-) diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h index bcfe10cf5..cce734fde 100644 --- a/src/AbstractTexture.h +++ b/src/AbstractTexture.h @@ -576,7 +576,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 +587,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/IndexedMesh.h b/src/IndexedMesh.h index 1a0b25e9f..8024ec614 100644 --- a/src/IndexedMesh.h +++ b/src/IndexedMesh.h @@ -81,6 +81,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 +96,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) { 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.h b/src/Mesh.h index 78a1ee686..2a1104548 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -388,6 +388,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 +403,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.h b/src/Platform/NaClApplication.h index bb66000b5..17de3da1c 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 @@ -71,41 +74,20 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient { ~NaClApplication(); + protected: + /** @{ @name Drawing functions */ - protected: - /** - * @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. - */ + /** @copydoc GlutApplication::viewportEvent() */ virtual void viewportEvent(const Math::Vector2& size) = 0; - /** - * @brief Draw 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(). - */ + /** @copydoc GlutApplication::drawEvent() */ virtual void drawEvent() = 0; - /** - * @brief Swap buffers - * - * Paints currently rendered framebuffer on screen. - */ + /** @copydoc GlutApplication::swapBuffers() */ void swapBuffers(); - /** - * @brief Redraw immediately - * - * Marks the window for redrawing, resulting in call of drawEvent() - * in the next iteration. - */ + /** @copydoc GlutApplication::redraw() */ inline void redraw() { flags |= Flag::Redraw; } /*@}*/ diff --git a/src/Platform/Sdl2Application.h b/src/Platform/Sdl2Application.h index 59b978420..26cd10920 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 @@ -223,7 +224,7 @@ class Sdl2Application { /** * @brief Mouse button * - * @see mouseEvent() + * @see mousePressEvent(), mouseReleaseEvent() */ enum class MouseButton: Uint8 { Left = SDL_BUTTON_LEFT, /**< Left button */ @@ -233,16 +234,6 @@ 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 */ - }; - protected: /** * @brief Mouse press event 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 { From 5354396af6adf43bc233217b41d57a2e87d76687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 16 Nov 2012 01:43:30 +0100 Subject: [PATCH 03/13] Sdl2Application: using special classes for input events. Will make lazy-loading possible and allows for less-constrained static polymorphism. --- src/Platform/Sdl2Application.cpp | 48 ++++--- src/Platform/Sdl2Application.h | 219 ++++++++++++++++++++++--------- 2 files changed, 182 insertions(+), 85 deletions(-) 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 26cd10920..3984f41da 100644 --- a/src/Platform/Sdl2Application.h +++ b/src/Platform/Sdl2Application.h @@ -54,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 @@ -79,9 +84,10 @@ class Sdl2Application { */ int exec(); + protected: + /** @{ @name Drawing functions */ - protected: /** @copydoc GlutApplication::viewportEvent() */ virtual void viewportEvent(const Math::Vector2& size) = 0; @@ -98,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 */ @@ -117,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 */ @@ -199,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 mousePressEvent(), mouseReleaseEvent() + * @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 */ @@ -234,47 +337,35 @@ class Sdl2Application { WheelDown = 5 /**< Wheel down */ }; - 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 Button */ + inline Button button() const { return _button; } - /** - * @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); + /** @brief Position */ + inline Math::Vector2 position() const { return _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); + private: + inline MouseEvent(Button button, const Math::Vector2& position): _button(button), _position(position) {} - /*@}*/ + const Button _button; + const Math::Vector2 _position; +}; - private: - SDL_Window* window; - SDL_GLContext context; +/** +@brief Mouse move event - Context* c; +@see MouseEvent, mouseMoveEvent() +*/ +class Sdl2Application::MouseMoveEvent: public Sdl2Application::InputEvent { + friend class Sdl2Application; - bool _redraw; + public: + /** @brief Position */ + inline Math::Vector2 position() const { return _position; } + + private: + inline MouseMoveEvent(const Math::Vector2& position): _position(position) {} + + const Math::Vector2 _position; }; /** @hideinitializer @@ -305,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&) {} }} From 0200ffe74ca4cfe97599564c6385e3c9e6c557c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 16 Nov 2012 01:44:41 +0100 Subject: [PATCH 04/13] NaClApplication: using special classes for input events. NaCl and SDL2 are now hotswappable again without any unimplemented or superfluous function parameters. Also added missing EnumSet operators for Modifiers. --- src/Platform/NaClApplication.cpp | 36 +++-- src/Platform/NaClApplication.h | 261 +++++++++++++++++++++---------- 2 files changed, 201 insertions(+), 96 deletions(-) diff --git a/src/Platform/NaClApplication.cpp b/src/Platform/NaClApplication.cpp index 1c57c2f14..c8af5f34e 100644 --- a/src/Platform/NaClApplication.cpp +++ b/src/Platform/NaClApplication.cpp @@ -83,27 +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()), {}); - break; - } case PP_INPUTEVENT_TYPE_MOUSEDOWN: { - pp::MouseInputEvent mouseEvent(event); - mousePressEvent(static_cast(mouseEvent.GetButton()), static_cast(mouseEvent.GetModifiers()), {mouseEvent.GetPosition().x(), mouseEvent.GetPosition().y()}); - break; - } case PP_INPUTEVENT_TYPE_MOUSEUP: { + } + + case PP_INPUTEVENT_TYPE_MOUSEDOWN: + case PP_INPUTEVENT_TYPE_MOUSEUP: { pp::MouseInputEvent mouseEvent(event); - mouseReleaseEvent(static_cast(mouseEvent.GetButton()), static_cast(mouseEvent.GetModifiers()), {mouseEvent.GetPosition().x(), mouseEvent.GetPosition().y()}); + 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: { + } + + case PP_INPUTEVENT_TYPE_MOUSEMOVE: { pp::MouseInputEvent mouseEvent(event); - mouseMotionEvent(static_cast(mouseEvent.GetModifiers()), {mouseEvent.GetPosition().x(), mouseEvent.GetPosition().y()}); + 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 17de3da1c..a064b2581 100644 --- a/src/Platform/NaClApplication.h +++ b/src/Platform/NaClApplication.h @@ -63,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 @@ -94,12 +99,103 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient { /** @{ @name Keyboard handling */ + /** + * @brief Key press event + * + * 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 keyPressEvent(KeyEvent& event); + + /** + * @brief Key release event + * + * 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 keyReleaseEvent(KeyEvent& event); + + /*@}*/ + + /** @{ @name Mouse handling */ + + /** + * @brief Mouse press event + * + * 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. + */ + virtual void mousePressEvent(MouseEvent& event); + + /** + * @brief Mouse release event + * + * 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. + */ + 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); + + /*@}*/ + + 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 */ @@ -118,16 +214,51 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient { /** * @brief Set of modifiers * - * @see keyPressEvent(), keyReleaseEvent(), mousePressEvent(), - * mouseReleaseEvent(), mouseMotionEvent() + * @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 */ @@ -199,99 +330,66 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient { Z = 'Z' /**< Letter Z */ }; - protected: - /** - * @brief Key press event - * @param key Key pressed - * @param modifiers Active modifiers - * @param position Cursor position (not implemented) - * - * Called when an key is pressed. Default implementation does nothing. - */ - 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); + private: + inline KeyEvent(Key key, Modifiers modifiers): InputEvent(modifiers), _key(key) {} - /*@}*/ + const Key _key; +}; - /** @{ @name Mouse handling */ +/** +@brief Mouse event + +See InputEvent for more information. +@see MouseMoveEvent, mousePressEvent(), mouseReleaseEvent() +*/ +class NaClApplication::MouseEvent: public NaClApplication::InputEvent { + friend class NaClApplication; public: /** - * @brief Mouse button + * @brief Button * - * @see mousePressEvent(), mouseReleaseEvent() + * @see button() */ - enum class MouseButton: unsigned int { + 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 */ }; - protected: - /** - * @brief Mouse press event - * @param button Button pressed - * @param modifiers Active modifiers - * @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 Button */ + inline Button button() const { return _button; } - /** - * @brief Mouse release event - * @param button Button released - * @param modifiers Active modifiers - * @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); - - /** - * @brief Mouse motion event - * @param modifiers Active modifiers - * @param position Cursor position - * - * Called when mouse is moved. - */ - virtual void mouseMotionEvent(Modifiers modifiers, const Math::Vector2& position); - - /*@}*/ + /** @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) @@ -339,13 +437,14 @@ When no other application header is included this macro is also aliased to #endif #endif -/* 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::mousePressEvent(MouseButton, Modifiers, const Math::Vector2&) {} -inline void NaClApplication::mouseReleaseEvent(MouseButton, Modifiers, const Math::Vector2&) {} -inline void NaClApplication::mouseMotionEvent(Modifiers, const Math::Vector2&) {} +CORRADE_ENUMSET_OPERATORS(NaClApplication::InputEvent::Modifiers) +/* Implementations for inline functions with unused parameters */ +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&) {} }} From a636792b19fca64a78c90ba5ae3efdaf65f51b59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 16 Nov 2012 11:14:30 +0100 Subject: [PATCH 05/13] AbstractShaderProgram: query for max supported attribute count. --- src/AbstractShaderProgram.cpp | 10 ++++++++++ src/AbstractShaderProgram.h | 21 ++++++++++++++++++--- src/Implementation/ShaderProgramState.h | 3 ++- 3 files changed, 30 insertions(+), 4 deletions(-) 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..28b3a63b1 100644 --- a/src/AbstractShaderProgram.h +++ b/src/AbstractShaderProgram.h @@ -273,7 +273,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 +298,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 +321,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 +447,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/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; }; }} From 8f83485653d8725ada20dec555e69d75e3107aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 16 Nov 2012 17:52:16 +0100 Subject: [PATCH 06/13] Forward declarations for Magnum namespace in Magnum.h header. --- doc/compilation-speedup.dox | 5 ++- src/AbstractShaderProgram.h | 6 ---- src/AbstractTexture.h | 4 --- src/Buffer.h | 2 -- src/BufferedTexture.h | 3 -- src/Color.h | 3 +- src/DimensionTraits.h | 2 -- src/Framebuffer.h | 14 -------- src/Magnum.h | 69 ++++++++++++++++++++++++++++++++++++- src/Mesh.h | 3 -- src/ResourceManager.h | 6 ++-- src/TypeTraits.h | 3 -- 12 files changed, 76 insertions(+), 44 deletions(-) diff --git a/doc/compilation-speedup.dox b/doc/compilation-speedup.dox index c1a0802f6..2ad9b2960 100644 --- a/doc/compilation-speedup.dox +++ b/doc/compilation-speedup.dox @@ -17,7 +17,10 @@ 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 @section compilation-speedup-templates Templates diff --git a/src/AbstractShaderProgram.h b/src/AbstractShaderProgram.h index 28b3a63b1..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; diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h index cce734fde..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 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 d3c794950..016fc1ee0 100644 --- a/src/DimensionTraits.h +++ b/src/DimensionTraits.h @@ -15,8 +15,6 @@ GNU Lesser General Public License version 3 for more details. */ -#include - #include "Magnum.h" /** @file 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/Magnum.h b/src/Magnum.h index 4a442f629..56579b81e 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 "magnumConfigure.h" #ifndef MAGNUM_TARGET_GLES @@ -94,6 +96,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/Mesh.h b/src/Mesh.h index 2a1104548..d33c94115 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -27,9 +27,6 @@ namespace Magnum { -class Buffer; -class Context; - /** @brief Non-indexed mesh diff --git a/src/ResourceManager.h b/src/ResourceManager.h index f603a8616..19147bb11 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, 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 From 681914e2d0246285e350019b3b5249752bf025dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 18 Nov 2012 18:42:45 +0100 Subject: [PATCH 07/13] Forward declarations for Shaders namespace in Shaders/Shaders.h. --- doc/compilation-speedup.dox | 1 + src/Shaders/CMakeLists.txt | 1 + src/Shaders/Shaders.h | 38 +++++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 src/Shaders/Shaders.h diff --git a/doc/compilation-speedup.dox b/doc/compilation-speedup.dox index 2ad9b2960..13dfef0ee 100644 --- a/doc/compilation-speedup.dox +++ b/doc/compilation-speedup.dox @@ -21,6 +21,7 @@ available, each namespace has its own: - Magnum.h - SceneGraph/SceneGraph.h + - Shaders/Shaders.h @section compilation-speedup-templates Templates 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 From 1809107ff2e174b77b5613d17577925f136e6c82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 18 Nov 2012 19:33:34 +0100 Subject: [PATCH 08/13] Resource: assert when accessing not loaded data. --- src/ResourceManager.h | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/ResourceManager.h b/src/ResourceManager.h index 19147bb11..bae717ad6 100644 --- a/src/ResourceManager.h +++ b/src/ResourceManager.h @@ -333,22 +333,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: From d3385b54c6f33d6c831f6a17482be337f03b558c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 19 Nov 2012 12:04:37 +0100 Subject: [PATCH 09/13] Default constructor of ResourceKey creates zero key. When resource access later fails on not loaded data, zero key in assertion message might hint that the Resource instance was default-constructed and thus not loaded at all. --- src/ResourceManager.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ResourceManager.h b/src/ResourceManager.h index bae717ad6..22a7097e4 100644 --- a/src/ResourceManager.h +++ b/src/ResourceManager.h @@ -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)) {} From 22cf5663c05c8fe28839d7cc161167ab29bcf53a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 19 Nov 2012 12:07:07 +0100 Subject: [PATCH 10/13] Use override keyword also here. --- src/IndexedMesh.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/IndexedMesh.h b/src/IndexedMesh.h index 8024ec614..9684d2305 100644 --- a/src/IndexedMesh.h +++ b/src/IndexedMesh.h @@ -115,7 +115,7 @@ 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; private: static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context); From 5ef729e89747c2974a47d0a639f57c439239c8d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 19 Nov 2012 12:08:12 +0100 Subject: [PATCH 11/13] Overloads in IndexedMesh to avoid WTFs in method chaining order. --- src/IndexedMesh.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/IndexedMesh.h b/src/IndexedMesh.h index 9684d2305..06af7e492 100644 --- a/src/IndexedMesh.h +++ b/src/IndexedMesh.h @@ -117,6 +117,30 @@ class MAGNUM_EXPORT IndexedMesh: public Mesh { */ 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); From 8abc836ae48aabe8744c1874ab20d97148e85baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 19 Nov 2012 12:10:51 +0100 Subject: [PATCH 12/13] Allow passing nullptr to IndexedMesh::setIndexBuffer(). Similar functionality should be in Mesh itself for unbinding vertex buffers. --- src/IndexedMesh.cpp | 8 +++++--- src/IndexedMesh.h | 3 +++ src/Mesh.h | 2 ++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/IndexedMesh.cpp b/src/IndexedMesh.cpp index e91453f74..4ef22584d 100644 --- a/src/IndexedMesh.cpp +++ b/src/IndexedMesh.cpp @@ -42,7 +42,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 +66,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 06af7e492..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) diff --git a/src/Mesh.h b/src/Mesh.h index d33c94115..d90687956 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -112,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; From 9b18e2b3e87200251b849c813a26be2fa05f1656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 19 Nov 2012 12:12:34 +0100 Subject: [PATCH 13/13] Don't issue draw call if there is nothing to draw. --- src/IndexedMesh.cpp | 2 ++ src/Mesh.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/IndexedMesh.cpp b/src/IndexedMesh.cpp index 4ef22584d..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 */ diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 4cb19a549..93ff6917e 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 */