diff --git a/engine/gf_draw_common.c b/engine/gf_draw_common.c index 13fe4f0..b81c83e 100644 --- a/engine/gf_draw_common.c +++ b/engine/gf_draw_common.c @@ -78,14 +78,18 @@ gf_draw_t* gf_draw_create(gf_engine_t* engine, const char* title) { void gf_draw_reshape(gf_draw_t* draw) { gf_draw_driver_reshape(draw); } -gf_gui_id_t button = -1; +gf_gui_id_t button1 = -1; +gf_gui_id_t button2 = -1; /* Runs every frame */ void gf_draw_frame(gf_draw_t* draw) { gf_graphic_color_t color; color.r = color.g = color.b = color.a = 255; - if(button == -1) { - button = gf_gui_create_button(draw->gui, 0, 0, 200, 100, "\"Test\" text"); + if(button1 == -1) { + button1 = gf_gui_create_button(draw->gui, 0, 0, 200, 50, "\"Test\" text"); + } + if(button2 == -1) { + button2 = gf_gui_create_button(draw->gui, 100, 25, 200, 50, "\"Test\" text"); } if(draw->draw_3d) { gf_graphic_draw_texture_polygon(draw, test_texture, color, GF_GRAPHIC_3D, 4, diff --git a/engine/gf_gui.c b/engine/gf_gui.c index 1df23d8..dd6aaf7 100644 --- a/engine/gf_gui.c +++ b/engine/gf_gui.c @@ -12,6 +12,7 @@ /* Engine */ #include #include +#include /* Standard */ #include @@ -27,6 +28,8 @@ gf_gui_t* gf_gui_create(gf_engine_t* engine, gf_draw_t* draw) { gui->engine = engine; gui->draw = draw; + gui->pressed = -1; + GF_SET_COLOR(gf_gui_base_color, 48, 96, 48, 255); GF_SET_COLOR(gf_gui_font_color, 256 - 32, 256 - 32, 256 - 32, 255); @@ -81,14 +84,32 @@ gf_gui_id_t gf_gui_create_button(gf_gui_t* gui, double x, double y, double w, do c->width = w; c->height = h; - c->u.button.pressed = 0; - c->u.button.text = malloc(strlen(text) + 1); + c->pressed = 0; + c->u.button.text = malloc(strlen(text) + 1); strcpy(c->u.button.text, text); return id; } void gf_gui_render(gf_gui_t* gui) { gf_gui_id_t i; + gf_input_t* input = gui->draw->input; + for(i = GF_GUI_MAX_COMPONENTS - 1; i >= 0; i--) { + gf_gui_component_t* c = &gui->area[i]; + double cx = c->x; + double cy = c->y; + double cw = c->width; + double ch = c->height; + switch(c->type) { + case GF_GUI_BUTTON: { + if((gui->pressed == -1) && (input->mouse_flag & GF_INPUT_MOUSE_LEFT_MASK) && (cx <= input->mouse_x && input->mouse_x <= cx + cw) && (cy <= input->mouse_y && input->mouse_y <= cy + ch)) { + gui->pressed = i; + } else if(gui->pressed == -1) { + c->pressed = 0; + } + break; + } + } + } for(i = 0; i < GF_GUI_MAX_COMPONENTS; i++) { gf_gui_component_t* c = &gui->area[i]; double cx = c->x; @@ -99,10 +120,15 @@ void gf_gui_render(gf_gui_t* gui) { case GF_GUI_BUTTON: { double x = cx + cw / 2 - gf_graphic_text_width(gui->draw, GF_GUI_FONT_SIZE, c->u.button.text) / 2; double y = cy + ch / 2 - GF_GUI_FONT_SIZE / 2; - gf_gui_draw_box(gui, GF_GUI_NORMAL, cx, cy, cw, ch); + gf_gui_draw_box(gui, (gui->pressed == i) ? GF_GUI_INVERT : GF_GUI_NORMAL, cx, cy, cw, ch); gf_graphic_text(gui->draw, x, y, GF_GUI_FONT_SIZE, c->u.button.text, gf_gui_font_color); break; } } } + if((gui->pressed != -1) && !(input->mouse_flag & GF_INPUT_MOUSE_LEFT_MASK)) { + gf_log_function(gui->engine, "GUI component %d was pressed", gui->pressed); + gui->area[gui->pressed].pressed = 1; + gui->pressed = -1; + } } diff --git a/engine/gf_input.c b/engine/gf_input.c index 9ed1bc5..57202f2 100644 --- a/engine/gf_input.c +++ b/engine/gf_input.c @@ -19,8 +19,9 @@ gf_input_t* gf_input_create(gf_engine_t* engine) { memset(input, 0, sizeof(input)); input->engine = engine; - input->mouse_x = 0; - input->mouse_y = 0; + input->mouse_x = 0; + input->mouse_y = 0; + input->mouse_flag = 0; return input; } diff --git a/engine/graphic/directx/dx11/gf_draw.c b/engine/graphic/directx/dx11/gf_draw.c index e1a1ab2..829c861 100644 --- a/engine/graphic/directx/dx11/gf_draw.c +++ b/engine/graphic/directx/dx11/gf_draw.c @@ -48,6 +48,36 @@ LRESULT CALLBACK gf_draw_platform_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp draw->input->mouse_y = HIWORD(lp); } break; + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + if(draw->input != NULL) { + if(msg == WM_LBUTTONDOWN) { + draw->input->mouse_flag |= GF_INPUT_MOUSE_LEFT_MASK; + } else { + draw->input->mouse_flag ^= GF_INPUT_MOUSE_LEFT_MASK; + } + } + break; + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + if(draw->input != NULL) { + if(msg == WM_MBUTTONDOWN) { + draw->input->mouse_flag |= GF_INPUT_MOUSE_MIDDLE_MASK; + } else { + draw->input->mouse_flag ^= GF_INPUT_MOUSE_MIDDLE_MASK; + } + } + break; + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + if(draw->input != NULL) { + if(msg == WM_RBUTTONDOWN) { + draw->input->mouse_flag |= GF_INPUT_MOUSE_RIGHT_MASK; + } else { + draw->input->mouse_flag ^= GF_INPUT_MOUSE_RIGHT_MASK; + } + } + break; case WM_CLOSE: draw->close = 1; break; diff --git a/engine/graphic/opengl/glfw/gf_draw.c b/engine/graphic/opengl/glfw/gf_draw.c index 62a1de8..a113f4a 100644 --- a/engine/graphic/opengl/glfw/gf_draw.c +++ b/engine/graphic/opengl/glfw/gf_draw.c @@ -38,6 +38,20 @@ void gf_glfw_size(GLFWwindow* window, int w, int h) { gf_draw_reshape(draw); } +void gf_glfw_button(GLFWwindow* window, int button, int action, int mods) { + gf_draw_t* draw = (gf_draw_t*)glfwGetWindowUserPointer(window); + if(draw->input != NULL) { + if(button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) draw->input->mouse_flag |= GF_INPUT_MOUSE_LEFT_MASK; + if(button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) draw->input->mouse_flag ^= GF_INPUT_MOUSE_LEFT_MASK; + + if(button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS) draw->input->mouse_flag |= GF_INPUT_MOUSE_RIGHT_MASK; + if(button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_RELEASE) draw->input->mouse_flag ^= GF_INPUT_MOUSE_RIGHT_MASK; + + if(button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_PRESS) draw->input->mouse_flag |= GF_INPUT_MOUSE_MIDDLE_MASK; + if(button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_RELEASE) draw->input->mouse_flag ^= GF_INPUT_MOUSE_MIDDLE_MASK; + } +} + void gf_glfw_cursor(GLFWwindow* window, double x, double y) { gf_draw_t* draw = (gf_draw_t*)glfwGetWindowUserPointer(window); if(draw->input != NULL) { @@ -88,6 +102,7 @@ gf_draw_platform_t* gf_draw_platform_create(gf_engine_t* engine, gf_draw_t* draw glfwSetWindowUserPointer(platform->window, draw); glfwSetCursorPosCallback(platform->window, gf_glfw_cursor); glfwSetWindowSizeCallback(platform->window, gf_glfw_size); + glfwSetMouseButtonCallback(platform->window, gf_glfw_button); glfwMakeContextCurrent(platform->window); #ifdef DO_SWAP_INTERVAL diff --git a/engine/graphic/opengl/glx/gf_draw.c b/engine/graphic/opengl/glx/gf_draw.c index be483b1..02d894a 100644 --- a/engine/graphic/opengl/glx/gf_draw.c +++ b/engine/graphic/opengl/glx/gf_draw.c @@ -97,7 +97,7 @@ gf_draw_platform_t* gf_draw_platform_create(gf_engine_t* engine, gf_draw_t* draw } attr.colormap = XCreateColormap(platform->display, root, visual->visual, AllocNone); - attr.event_mask = StructureNotifyMask | ExposureMask | PointerMotionMask; + attr.event_mask = StructureNotifyMask | ExposureMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask; platform->window = XCreateWindow(platform->display, root, draw->width, draw->height, draw->width, draw->height, 0, visual->depth, InputOutput, visual->visual, CWColormap | CWEventMask, &attr); hints.x = draw->x; @@ -172,6 +172,18 @@ int gf_draw_platform_step(gf_draw_t* draw) { draw->height = event.xconfigure.height; glXMakeCurrent(draw->platform->display, draw->platform->window, draw->platform->context); gf_draw_reshape(draw); + } else if(event.type == ButtonPress) { + if(draw->input != NULL) { + if(event.xbutton.button == Button1) draw->input->mouse_flag |= GF_INPUT_MOUSE_LEFT_MASK; + if(event.xbutton.button == Button2) draw->input->mouse_flag |= GF_INPUT_MOUSE_MIDDLE_MASK; + if(event.xbutton.button == Button3) draw->input->mouse_flag |= GF_INPUT_MOUSE_RIGHT_MASK; + } + } else if(event.type == ButtonRelease) { + if(draw->input != NULL) { + if(event.xbutton.button == Button1) draw->input->mouse_flag ^= GF_INPUT_MOUSE_LEFT_MASK; + if(event.xbutton.button == Button2) draw->input->mouse_flag ^= GF_INPUT_MOUSE_MIDDLE_MASK; + if(event.xbutton.button == Button3) draw->input->mouse_flag ^= GF_INPUT_MOUSE_RIGHT_MASK; + } } else if(event.type == ClientMessage) { if(event.xclient.data.l[0] == draw->platform->wm_delete_window) { draw->close = 1; diff --git a/engine/graphic/opengl/wgl/gf_draw.c b/engine/graphic/opengl/wgl/gf_draw.c index 8a54db4..7276c7b 100644 --- a/engine/graphic/opengl/wgl/gf_draw.c +++ b/engine/graphic/opengl/wgl/gf_draw.c @@ -54,6 +54,36 @@ LRESULT CALLBACK gf_draw_platform_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp draw->input->mouse_y = HIWORD(lp); } break; + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + if(draw->input != NULL) { + if(msg == WM_LBUTTONDOWN) { + draw->input->mouse_flag |= GF_INPUT_MOUSE_LEFT_MASK; + } else { + draw->input->mouse_flag ^= GF_INPUT_MOUSE_LEFT_MASK; + } + } + break; + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + if(draw->input != NULL) { + if(msg == WM_MBUTTONDOWN) { + draw->input->mouse_flag |= GF_INPUT_MOUSE_MIDDLE_MASK; + } else { + draw->input->mouse_flag ^= GF_INPUT_MOUSE_MIDDLE_MASK; + } + } + break; + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + if(draw->input != NULL) { + if(msg == WM_RBUTTONDOWN) { + draw->input->mouse_flag |= GF_INPUT_MOUSE_RIGHT_MASK; + } else { + draw->input->mouse_flag ^= GF_INPUT_MOUSE_RIGHT_MASK; + } + } + break; case WM_CLOSE: draw->close = 1; break; diff --git a/engine/include/gf_type/gui.h b/engine/include/gf_type/gui.h index 93cb1b8..84a378c 100644 --- a/engine/include/gf_type/gui.h +++ b/engine/include/gf_type/gui.h @@ -53,14 +53,8 @@ enum GF_GUI_COMPONENT_TYPES { * * @var gf_gui_button_t::text * @brief Button text - * - * @var gf_gui_button_t::pressed - * @brief `1` if pressed, otherwise `0` */ -GF_DECLARE_TYPE(gui_button, { - char* text; - int pressed; -}); +GF_DECLARE_TYPE(gui_button, { char* text; }); /** * @union gf_gui_union_t @@ -97,6 +91,9 @@ typedef union gf_gui_union_t { * * @var gf_gui_component_t::u * @brief Component union + * + * @var gf_gui_component_t::pressed + * @brief `1` if pressed, otherwise `0` */ GF_DECLARE_TYPE(gui_component, { int type; @@ -104,6 +101,7 @@ GF_DECLARE_TYPE(gui_component, { double y; double width; double height; + int pressed; gf_gui_union_t u; }); @@ -118,12 +116,16 @@ GF_DECLARE_TYPE(gui_component, { * @var gf_gui_t::draw * @brief Drawing interface * + * @var gf_gui_t::pressed + * @brief `1` if something is being pressed, otherwise `0` + * * @var gf_gui_t::area * @brief Created components */ GF_DECLARE_TYPE(gui, { gf_engine_t* engine; gf_draw_t* draw; + gf_gui_id_t pressed; gf_gui_component_t area[GF_GUI_MAX_COMPONENTS]; }); #else diff --git a/engine/include/gf_type/input.h b/engine/include/gf_type/input.h index 30805ee..c495193 100644 --- a/engine/include/gf_type/input.h +++ b/engine/include/gf_type/input.h @@ -21,6 +21,24 @@ typedef struct gf_input_t gf_input_t; /* Standard */ +/** + * @~english + * @brief Mask for left mouse button + */ +#define GF_INPUT_MOUSE_LEFT_MASK (1 << 0) + +/** + * @~english + * @brief Mask for middle mouse button + */ +#define GF_INPUT_MOUSE_MIDDLE_MASK (1 << 1) + +/** + * @~english + * @brief Mask for right mouse button + */ +#define GF_INPUT_MOUSE_RIGHT_MASK (1 << 2) + /** * @struct gf_input_t * @~english @@ -34,11 +52,15 @@ typedef struct gf_input_t gf_input_t; * * @var gf_input_t::mouse_y * @brief Y coord of mouse + * + * @var gf_input_t::mouse_flag + * @brief Mouse flag */ GF_DECLARE_TYPE(input, { gf_engine_t* engine; int mouse_x; int mouse_y; + int mouse_flag; }); #else typedef void gf_input_t;