v4k-git-backup/engine/split/3rd_lite_sys_gleq.h

425 lines
12 KiB
C

/*
* GLEQ - A basic event queue for GLFW 3
* Copyright © Camilla Löwy <elmindreda@glfw.org>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef GLEQ_HEADER_FILE
#define GLEQ_HEADER_FILE
// #include <GLFW/glfw3.h>
#ifdef GLEQ_STATIC
#define GLEQDEF static
#else
#define GLEQDEF extern
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
GLEQ_NONE = 0,
GLEQ_WINDOW_MOVED = 1<<1,
GLEQ_WINDOW_RESIZED = 1<<2,
GLEQ_WINDOW_CLOSED = 1<<3,
GLEQ_WINDOW_REFRESH = 1<<4,
GLEQ_WINDOW_FOCUSED = 1<<5,
GLEQ_WINDOW_DEFOCUSED = 1<<6,
GLEQ_WINDOW_ICONIFIED = 1<<7,
GLEQ_WINDOW_UNICONIFIED = 1<<8,
GLEQ_FRAMEBUFFER_RESIZED = 1<<9,
GLEQ_BUTTON_PRESSED = 1<<10,
GLEQ_BUTTON_RELEASED = 1<<11,
GLEQ_CURSOR_MOVED = 1<<12,
GLEQ_CURSOR_ENTERED = 1<<13,
GLEQ_CURSOR_LEFT = 1<<14,
GLEQ_SCROLLED = 1<<15,
GLEQ_KEY_PRESSED = 1<<16,
GLEQ_KEY_REPEATED = 1<<17,
GLEQ_KEY_RELEASED = 1<<18,
GLEQ_CODEPOINT_INPUT = 1<<19,
GLEQ_MONITOR_CONNECTED = 1<<20,
GLEQ_MONITOR_DISCONNECTED = 1<<21,
#if GLFW_VERSION_MINOR >= 1
GLEQ_FILE_DROPPED = 1<<22,
#endif
#if GLFW_VERSION_MINOR >= 2
GLEQ_JOYSTICK_CONNECTED = 1<<23,
GLEQ_JOYSTICK_DISCONNECTED = 1<<24,
#endif
#if GLFW_VERSION_MINOR >= 3
GLEQ_WINDOW_MAXIMIZED = 1<<25,
GLEQ_WINDOW_UNMAXIMIZED = 1<<26,
GLEQ_WINDOW_SCALE_CHANGED = 1<<27,
#endif
} GLEQtype;
typedef struct GLEQevent
{
unsigned/*GLEQtype*/ type;
union {
GLFWwindow* window;
GLFWmonitor* monitor;
int joystick;
};
union {
struct {
int x;
int y;
} pos;
struct {
int width;
int height;
} size;
struct {
double x;
double y;
} scroll;
struct {
int key;
int scancode;
int mods;
} keyboard;
struct {
int button;
int mods;
} mouse;
unsigned int codepoint;
#if GLFW_VERSION_MINOR >= 1
struct {
char** paths;
int count;
} file;
#endif
#if GLFW_VERSION_MINOR >= 3
struct {
float x;
float y;
} scale;
#endif
};
} GLEQevent;
GLEQDEF void gleqInit(void);
GLEQDEF void gleqTrackWindow(GLFWwindow* window);
GLEQDEF int gleqNextEvent(GLEQevent* event);
GLEQDEF void gleqFreeEvent(GLEQevent* event);
#ifdef __cplusplus
}
#endif
#ifdef GLEQ_IMPLEMENTATION
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifndef GLEQ_CAPACITY
#define GLEQ_CAPACITY 1024
#endif
static struct
{
GLEQevent events[GLEQ_CAPACITY];
size_t head;
size_t tail;
} gleq_queue = { {0}, 0, 0 };
static char* gleq_strdup(const char* string)
{
const size_t size = strlen(string) + 1;
char* result = (char*) malloc(size);
memcpy(result, string, size);
return result;
}
static GLEQevent* gleq_new_event(void)
{
GLEQevent* event = gleq_queue.events + gleq_queue.head;
gleq_queue.head = (gleq_queue.head + 1) % GLEQ_CAPACITY;
assert(gleq_queue.head != gleq_queue.tail);
memset(event, 0, sizeof(GLEQevent));
return event;
}
static void gleq_window_pos_callback(GLFWwindow* window, int x, int y)
{
GLEQevent* event = gleq_new_event();
event->type = GLEQ_WINDOW_MOVED;
event->window = window;
event->pos.x = x;
event->pos.y = y;
}
static void gleq_window_size_callback(GLFWwindow* window, int width, int height)
{
GLEQevent* event = gleq_new_event();
event->type = GLEQ_WINDOW_RESIZED;
event->window = window;
event->size.width = width;
event->size.height = height;
}
static void gleq_window_close_callback(GLFWwindow* window)
{
GLEQevent* event = gleq_new_event();
event->type = GLEQ_WINDOW_CLOSED;
event->window = window;
}
static void gleq_window_refresh_callback(GLFWwindow* window)
{
GLEQevent* event = gleq_new_event();
event->type = GLEQ_WINDOW_REFRESH;
event->window = window;
}
static void gleq_window_focus_callback(GLFWwindow* window, int focused)
{
GLEQevent* event = gleq_new_event();
event->window = window;
if (focused)
event->type = GLEQ_WINDOW_FOCUSED;
else
event->type = GLEQ_WINDOW_DEFOCUSED;
}
static void gleq_window_iconify_callback(GLFWwindow* window, int iconified)
{
GLEQevent* event = gleq_new_event();
event->window = window;
if (iconified)
event->type = GLEQ_WINDOW_ICONIFIED;
else
event->type = GLEQ_WINDOW_UNICONIFIED;
}
static void gleq_framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
GLEQevent* event = gleq_new_event();
event->type = GLEQ_FRAMEBUFFER_RESIZED;
event->window = window;
event->size.width = width;
event->size.height = height;
}
static void gleq_mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
GLEQevent* event = gleq_new_event();
event->window = window;
event->mouse.button = button;
event->mouse.mods = mods;
if (action == GLFW_PRESS)
event->type = GLEQ_BUTTON_PRESSED;
else if (action == GLFW_RELEASE)
event->type = GLEQ_BUTTON_RELEASED;
}
static void gleq_cursor_pos_callback(GLFWwindow* window, double x, double y)
{
GLEQevent* event = gleq_new_event();
event->type = GLEQ_CURSOR_MOVED;
event->window = window;
event->pos.x = (int) x;
event->pos.y = (int) y;
}
static void gleq_cursor_enter_callback(GLFWwindow* window, int entered)
{
GLEQevent* event = gleq_new_event();
event->window = window;
if (entered)
event->type = GLEQ_CURSOR_ENTERED;
else
event->type = GLEQ_CURSOR_LEFT;
}
static void gleq_scroll_callback(GLFWwindow* window, double x, double y)
{
GLEQevent* event = gleq_new_event();
event->type = GLEQ_SCROLLED;
event->window = window;
event->scroll.x = x;
event->scroll.y = y;
}
static void gleq_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
GLEQevent* event = gleq_new_event();
event->window = window;
event->keyboard.key = key;
event->keyboard.scancode = scancode;
event->keyboard.mods = mods;
if (action == GLFW_PRESS)
event->type = GLEQ_KEY_PRESSED;
else if (action == GLFW_RELEASE)
event->type = GLEQ_KEY_RELEASED;
else if (action == GLFW_REPEAT)
event->type = GLEQ_KEY_REPEATED;
}
static void (*gleq_char_callback_prev)(GLFWwindow* window, unsigned int codepoint) = 0;
static void gleq_char_callback(GLFWwindow* window, unsigned int codepoint)
{
if( gleq_char_callback_prev )
gleq_char_callback_prev(window, codepoint);
GLEQevent* event = gleq_new_event();
event->type = GLEQ_CODEPOINT_INPUT;
event->window = window;
event->codepoint = codepoint;
}
static void gleq_monitor_callback(GLFWmonitor* monitor, int action)
{
GLEQevent* event = gleq_new_event();
event->monitor = monitor;
if (action == GLFW_CONNECTED)
event->type = GLEQ_MONITOR_CONNECTED;
else if (action == GLFW_DISCONNECTED)
event->type = GLEQ_MONITOR_DISCONNECTED;
}
#if GLFW_VERSION_MINOR >= 1
static void gleq_file_drop_callback(GLFWwindow* window, int count, const char** paths)
{
GLEQevent* event = gleq_new_event();
event->type = GLEQ_FILE_DROPPED;
event->window = window;
event->file.paths = (char**) malloc(count * sizeof(char*));
event->file.count = count;
while (count--)
event->file.paths[count] = gleq_strdup(paths[count]);
}
#endif
#if GLFW_VERSION_MINOR >= 2
static void gleq_joystick_callback(int jid, int action)
{
GLEQevent* event = gleq_new_event();
event->joystick = jid;
if (action == GLFW_CONNECTED)
event->type = GLEQ_JOYSTICK_CONNECTED;
else if (action == GLFW_DISCONNECTED)
event->type = GLEQ_JOYSTICK_DISCONNECTED;
}
#endif
#if GLFW_VERSION_MINOR >= 3
static void gleq_window_maximize_callback(GLFWwindow* window, int maximized)
{
GLEQevent* event = gleq_new_event();
event->window = window;
if (maximized)
event->type = GLEQ_WINDOW_MAXIMIZED;
else
event->type = GLEQ_WINDOW_UNMAXIMIZED;
}
static void gleq_window_content_scale_callback(GLFWwindow* window, float xscale, float yscale)
{
GLEQevent* event = gleq_new_event();
event->window = window;
event->type = GLEQ_WINDOW_SCALE_CHANGED;
event->scale.x = xscale;
event->scale.y = yscale;
}
#endif
GLEQDEF void gleqInit(void)
{
glfwSetMonitorCallback(gleq_monitor_callback);
#if GLFW_VERSION_MINOR >= 2
glfwSetJoystickCallback(gleq_joystick_callback);
#endif
}
GLEQDEF void gleqTrackWindow(GLFWwindow* window)
{
glfwSetWindowPosCallback(window, gleq_window_pos_callback);
glfwSetWindowSizeCallback(window, gleq_window_size_callback);
glfwSetWindowCloseCallback(window, gleq_window_close_callback);
glfwSetWindowRefreshCallback(window, gleq_window_refresh_callback);
glfwSetWindowFocusCallback(window, gleq_window_focus_callback);
glfwSetWindowIconifyCallback(window, gleq_window_iconify_callback);
glfwSetFramebufferSizeCallback(window, gleq_framebuffer_size_callback);
glfwSetMouseButtonCallback(window, gleq_mouse_button_callback);
glfwSetCursorPosCallback(window, gleq_cursor_pos_callback);
glfwSetCursorEnterCallback(window, gleq_cursor_enter_callback);
glfwSetScrollCallback(window, gleq_scroll_callback);
glfwSetKeyCallback(window, gleq_key_callback);
gleq_char_callback_prev = //< @r-lyeh
glfwSetCharCallback(window, gleq_char_callback);
#if GLFW_VERSION_MINOR >= 1
glfwSetDropCallback(window, gleq_file_drop_callback);
#endif
#if GLFW_VERSION_MINOR >= 3
glfwSetWindowMaximizeCallback(window, gleq_window_maximize_callback);
glfwSetWindowContentScaleCallback(window, gleq_window_content_scale_callback);
#endif
}
GLEQDEF int gleqNextEvent(GLEQevent* event)
{
memset(event, 0, sizeof(GLEQevent));
if (gleq_queue.head != gleq_queue.tail)
{
*event = gleq_queue.events[gleq_queue.tail];
gleq_queue.tail = (gleq_queue.tail + 1) % GLEQ_CAPACITY;
}
return event->type != GLEQ_NONE;
}
GLEQDEF void gleqFreeEvent(GLEQevent* event)
{
#if GLFW_VERSION_MINOR >= 1
if (event->type == GLEQ_FILE_DROPPED)
{
while (event->file.count--)
free(event->file.paths[event->file.count]);
free(event->file.paths);
}
#endif
memset(event, 0, sizeof(GLEQevent));
}
#endif /* GLEQ_IMPLEMENTATION */
#endif /* GLEQ_HEADER_FILE */