Hello all, I’m looking into making an object oriented toolkit and have ran into a bit of a snag with glut’s idle function callback. The problem is that I can’t seem to attach a dedicated idle function callback on a per-window basis. Is there any way to make glut accept idle functions on a per-window basis? Thanks for any help.
Below is what I have mocked together so far (It’s a bit long, but cannot be further compressed for a SSCCE, sorry):
(Note: The code is in C++11, only Clang is supported, though GCC might work)
#ifndef BOOTSTRAP_HPP
#define BOOTSTRAP_HPP
#include <iostream>
#include <map>
#include "Platform.hpp"
namespace detail
{
struct VirtualBootstrap
{
protected:
static thread_local bool glew_initialized;
public:
virtual void idle() = 0;
virtual void tick() = 0;
virtual void render() = 0;
virtual ~VirtualBootstrap() = default;
};
thread_local bool VirtualBootstrap::glew_initialized = false;
thread_local std::map<int, VirtualBootstrap*> bootstraps;
template<int N>
void register_this(VirtualBootstrap* bootstrap) noexcept
{
bootstraps.insert(std::make_pair(N, bootstrap));
}
template<int N>
void unregister_this() noexcept
{
bootstraps.erase(N);
}
template<int N>
void glutDisplayFuncDelegate()
{
std::cout << N << " rendering" << std::endl;
bootstraps[N]->render();
}
template<int N>
void glutIdleFuncDelegate()
{
std::cout << N << " idling" << std::endl;
bootstraps[N]->idle();
}
}
template<int N>
class Bootstrap : public detail::VirtualBootstrap
{
public:
Bootstrap(int windowWidth, int windowHeight)
{
glutInitWindowSize(windowWidth, windowHeight);
glutInitWindowPosition(100, 100);
glutCreateWindow((std::string("Bootstrap Test (") + std::to_string(N) + ")").c_str());
if(!glew_initialized)
{
glewInit();
glew_initialized = true;
}
glutDisplayFunc(detail::glutDisplayFuncDelegate<N>);
glutIdleFunc(detail::glutIdleFuncDelegate<N>);
detail::register_this<N>(this);
}
virtual ~Bootstrap()
{
detail::unregister_this<N>();
}
};
template<int N>
class TestBootstrap : public Bootstrap<N>
{
public:
TestBootstrap(int w, int h) : Bootstrap<N>(w, h) {}
virtual void idle() { /** update some uniforms... */ glutPostRedisplay();}
virtual void tick() {}
virtual void render() { /** Render something impressive */}
};
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA);
TestBootstrap<0> bootstrap0(300, 300);
TestBootstrap<1> bootstrap1(300, 300);
glutMainLoop();
}
#endif