Browse Source

Add tick event in Glfw applications

Linked: #577
pull/580/head
Andreas Leroux 4 years ago
parent
commit
7f045b5d7d
  1. 51
      src/Magnum/Platform/GlfwApplication.cpp
  2. 33
      src/Magnum/Platform/GlfwApplication.h

51
src/Magnum/Platform/GlfwApplication.cpp

@ -33,6 +33,7 @@
#include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Utility/Arguments.h>
#include <Corrade/Utility/Unicode.h>
#include <Corrade/Utility/System.h>
#include "Magnum/ImageView.h"
#include "Magnum/PixelFormat.h"
@ -56,9 +57,10 @@ static_assert(GLFW_TRUE == true && GLFW_FALSE == false, "GLFW does not have sane
enum class GlfwApplication::Flag: UnsignedByte {
Redraw = 1 << 0,
TextInputActive = 1 << 1,
Exit = 1 << 2,
NoTickEvent = 1 << 2,
Exit = 1 << 3,
#ifdef CORRADE_TARGET_APPLE
HiDpiWarningPrinted = 1 << 3
HiDpiWarningPrinted = 1 << 4
#endif
};
@ -75,7 +77,7 @@ GlfwApplication::GlfwApplication(const Arguments& arguments, const Configuration
#endif
GlfwApplication::GlfwApplication(const Arguments& arguments, NoCreateT):
_flags{Flag::Redraw}
_minimalLoopPeriod{0}, _flags{Flag::Redraw}
{
Utility::Arguments args{Implementation::windowScalingArguments()};
#ifdef MAGNUM_TARGET_GL
@ -762,15 +764,36 @@ bool GlfwApplication::mainLoopIteration() {
*/
if(glfwGetWindowUserPointer(_window) != this) setupCallbacks();
/* If redrawing, poll for events immediately after drawEvent() (which could
be setting the Redraw flag again, thus doing constant redraw). If not,
avoid spinning the CPU by waiting for the next input event. */
if (mainLoopDrawEventIteration())
glfwPollEvents();
else
glfwWaitEvents();
const UnsignedInt timeBefore = _minimalLoopPeriod ? glfwGetTime() : 0;
return !glfwWindowShouldClose(_window);
glfwPollEvents();
/* Tick event */
if(!(_flags & Flag::NoTickEvent)) tickEvent();
/* drawEvent() was called */
if (mainLoopDrawEventIteration()) {
/* delay to prevent CPU hogging (if set) */
if(!(_minimalLoopPeriod) {
const UnsignedInt loopTime = glfwGetTime() - timeBefore;
if(loopTime < _minimalLoopPeriod)
Utility::System::sleep(_minimalLoopPeriod - loopTime);
}
return !glfwWindowShouldClose(_window);
}
/* If not drawing anything, delay to prevent CPU hogging (if set) */
if(_minimalLoopPeriod) {
const UnsignedInt loopTime = glfwGetTime() - timeBefore;
if(loopTime < _minimalLoopPeriod)
Utility::System::sleep(_minimalLoopPeriod - loopTime);
}
/* Then, if the tick event doesn't need to be called periodically, wait
indefinitely for next input event */
if(_flags & Flag::NoTickEvent) glfwWaitEvents();
return !(flags & Flag::Exit || glfwWindowShouldClose(_window));
}
void GlfwApplication::exit(int exitCode) {
@ -871,6 +894,12 @@ void GlfwApplication::exitEvent(ExitEvent& event) {
event.setAccepted();
}
void GlfwApplication::tickEvent() {
/* If this got called, the tick event is not implemented by user and thus
we don't need to call it ever again */
_flags |= Flag::NoTickEvent;
}
void GlfwApplication::viewportEvent(ViewportEvent&) {}
void GlfwApplication::keyPressEvent(KeyEvent&) {}
void GlfwApplication::keyReleaseEvent(KeyEvent&) {}

33
src/Magnum/Platform/GlfwApplication.h

@ -543,6 +543,21 @@ class GlfwApplication {
*/
void setSwapInterval(Int interval);
/**
* @brief Set minimal loop period
*
* This setting reduces the main loop frequency in case VSync is
* not/cannot be enabled or no drawing is done. Default is @cpp 0 @ce
* (i.e. looping at maximum frequency). If the application is drawing
* on the screen and VSync is enabled, this setting is ignored.
* @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten",
* the browser is managing the frequency instead.
* @see @ref setSwapInterval()
*/
void setMinimalLoopPeriod(UnsignedInt milliseconds) {
_minimalLoopPeriod = milliseconds;
}
/** @copydoc Sdl2Application::redraw() */
void redraw();
@ -753,6 +768,23 @@ class GlfwApplication {
* @}
*/
protected:
/**
* @brief Tick event
*
* If implemented, this function is called periodically after
* processing all input events and before draw event even though there
* might be no input events and redraw is not requested. Useful e.g.
* for asynchronous task polling. Use @ref setMinimalLoopPeriod()/
* @ref setSwapInterval() to control main loop frequency.
*
* If this implementation gets called from its @cpp override @ce, it
* will effectively stop the tick event from being fired and the app
* returns back to waiting for input events. This can be used to
* disable the tick event when not needed.
*/
virtual void tickEvent();
private:
enum class Flag: UnsignedByte;
typedef Containers::EnumSet<Flag> Flags;
@ -778,6 +810,7 @@ class GlfwApplication {
Vector2 _dpiScaling;
GLFWwindow* _window{nullptr};
UnsignedInt _minimalLoopPeriod;
Flags _flags;
#ifdef MAGNUM_TARGET_GL
/* Has to be in an Optional because we delay-create it in a constructor

Loading…
Cancel
Save