174 lines
3.7 KiB
C++
174 lines
3.7 KiB
C++
#include "gl3w.h"
|
|
#include "GLBuffer.h"
|
|
#include "ruby.h"
|
|
#include "Window.h"
|
|
#include <SDL.h>
|
|
|
|
#define WIDTH 500
|
|
#define HEIGHT 500
|
|
|
|
typedef struct
|
|
{
|
|
SDL_Window * sdl_window;
|
|
GLBufferRef rect_buffer;
|
|
} Window;
|
|
|
|
static VALUE ruby_class;
|
|
static VALUE window_instance;
|
|
|
|
static void Init_SDL()
|
|
{
|
|
static bool initialized = false;
|
|
|
|
if (initialized)
|
|
return;
|
|
|
|
if (SDL_Init(SDL_INIT_VIDEO))
|
|
{
|
|
rb_raise(rb_eRuntimeError, "Failed to initialize SDL");
|
|
}
|
|
|
|
atexit(SDL_Quit);
|
|
|
|
initialized = true;
|
|
}
|
|
|
|
static void load_gl_buffers(Window * window)
|
|
{
|
|
static const GLint rect_coords[4][2] = {
|
|
{0, 0},
|
|
{1, 0},
|
|
{0, 1},
|
|
{1, 1},
|
|
};
|
|
|
|
window->rect_buffer = new GLBuffer();
|
|
if (!window->rect_buffer->create(GL_ARRAY_BUFFER, GL_STATIC_DRAW,
|
|
&rect_coords, sizeof(rect_coords)))
|
|
{
|
|
rb_raise(rb_eRuntimeError, "Failed to create rectangle VBO");
|
|
}
|
|
}
|
|
|
|
static void Init_OpenGL()
|
|
{
|
|
static bool initialized = false;
|
|
|
|
if (initialized)
|
|
return;
|
|
|
|
if (gl3wInit() != 0)
|
|
{
|
|
SDL_Quit();
|
|
rb_raise(rb_eRuntimeError, "Failed to gl3wInit()");
|
|
}
|
|
|
|
if (!gl3wIsSupported(3, 0))
|
|
{
|
|
SDL_Quit();
|
|
rb_raise(rb_eRuntimeError, "OpenGL 3.0 is not supported");
|
|
}
|
|
|
|
initialized = true;
|
|
}
|
|
|
|
static void Window_free(void * ptr)
|
|
{
|
|
Window * window = (Window *)ptr;
|
|
|
|
if (window->sdl_window)
|
|
SDL_DestroyWindow(window->sdl_window);
|
|
|
|
delete window;
|
|
}
|
|
|
|
static VALUE Window_new(VALUE klass)
|
|
{
|
|
static bool one_created = false;
|
|
|
|
if (one_created)
|
|
{
|
|
rb_raise(rb_eRuntimeError, "Only one Window for now");
|
|
}
|
|
|
|
Init_SDL();
|
|
|
|
SDL_Window * sdl_window =
|
|
SDL_CreateWindow("jes",
|
|
SDL_WINDOWPOS_UNDEFINED,
|
|
SDL_WINDOWPOS_UNDEFINED,
|
|
WIDTH,
|
|
HEIGHT,
|
|
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
|
|
if (sdl_window == NULL)
|
|
{
|
|
rb_raise(rb_eRuntimeError, "Failed to create SDL window");
|
|
}
|
|
|
|
Window * window = new Window();
|
|
window->sdl_window = sdl_window;
|
|
|
|
(void)SDL_GL_CreateContext(window->sdl_window);
|
|
|
|
Init_OpenGL();
|
|
|
|
load_gl_buffers(window);
|
|
|
|
one_created = true;
|
|
|
|
VALUE rv = Data_Wrap_Struct(ruby_class, NULL, Window_free, window);
|
|
rb_obj_call_init(rv, 0, NULL);
|
|
/* TODO: remove window_instance and map SDL_Window * to Window Ruby object
|
|
* to support multiple windows. */
|
|
window_instance = rv;
|
|
|
|
return rv;
|
|
}
|
|
|
|
static void resize()
|
|
{
|
|
GLint viewport_size[2];
|
|
Window * window;
|
|
Data_Get_Struct(window_instance, Window, window);
|
|
SDL_GetWindowSize(window->sdl_window, &viewport_size[0], &viewport_size[1]);
|
|
glViewport(0, 0, viewport_size[0], viewport_size[1]);
|
|
}
|
|
|
|
static VALUE Window_event_loop(VALUE klass)
|
|
{
|
|
SDL_Event event;
|
|
|
|
while (SDL_WaitEvent(&event))
|
|
{
|
|
if (event.type == SDL_QUIT)
|
|
break;
|
|
else if (event.type == SDL_KEYDOWN)
|
|
{
|
|
if (event.key.keysym.sym == SDLK_ESCAPE)
|
|
break;
|
|
}
|
|
else if (event.type == SDL_WINDOWEVENT)
|
|
{
|
|
switch (event.window.event)
|
|
{
|
|
case SDL_WINDOWEVENT_EXPOSED:
|
|
// draw();
|
|
break;
|
|
case SDL_WINDOWEVENT_RESIZED:
|
|
resize();
|
|
// draw();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return Qnil;
|
|
}
|
|
|
|
void Window_Init(void)
|
|
{
|
|
ruby_class = rb_define_class("Window", rb_cObject);
|
|
rb_define_singleton_method(ruby_class, "new", (VALUE(*)(...))Window_new, 0);
|
|
rb_define_singleton_method(ruby_class, "event_loop", (VALUE(*)(...))Window_event_loop, 0);
|
|
}
|