From a3f4639a90f2c8bdceb0966a1596e9781de78005 Mon Sep 17 00:00:00 2001 From: Rusty Striker Date: Wed, 5 Jul 2023 12:24:14 +0300 Subject: [PATCH] sliders can now draw and slide using mousewheel --- mmn_17.c | 52 +++++++++++++++++++++++++++++++++++++++++++++- ui.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++------- ui.h | 7 ++++--- 3 files changed, 110 insertions(+), 12 deletions(-) diff --git a/mmn_17.c b/mmn_17.c index c03dce7..18075dd 100644 --- a/mmn_17.c +++ b/mmn_17.c @@ -14,8 +14,17 @@ ui_button buttons[] = { /* text */ "Test :)" } }; +ui_slider sliders[] = { + { + /* pos */ { { 0.5, 0.7, 0.0 }, {-50.0, -5.0, 0.0 } }, + /* size */ { 100.0, 10.0, 10.0 }, + 0.1 + } +}; + void display(void) { + printf("Drawing!\n"); // Clear screen glClearColor(0.0, 0.0, 0.0, 1.0); // Dark theme :) glClear(GL_COLOR_BUFFER_BIT); @@ -23,6 +32,10 @@ void display(void) { for(ui_button* b = buttons; b < buttons + sizeof buttons / sizeof(ui_button); b += 1) { ui_button_draw(b); } + for(ui_slider* s = sliders; s < sliders + sizeof sliders / sizeof(ui_slider); s += 1) { + ui_slider_draw(s); + } + int err = glGetError(); if(err != 0) { printf("opengl error %d: %s\n", err, gluErrorString(err)); @@ -32,7 +45,42 @@ void display(void) { } void mouseEvent(int button, int state, int x, int y) { - + if(state == 1) { + for(ui_button* b = buttons; b < buttons + sizeof buttons / sizeof(ui_button); b += 1) { + if(ui_button_mouse_over(b, x, y) && b->onClick != NULL) { + b->onClick(); + return; + } + } + } + for(ui_slider* s = sliders; s < sliders + sizeof sliders / sizeof(ui_slider); s += 1) { + if(ui_slider_mouse_over(s, x, y)) { + ui_slider_onclick(s, x, y, button, state); + } + } +} + +void mouseWheelEvent(int wheel, int dir, int x, int y) { + printf("wheel event\n"); + for(ui_slider* s = sliders; s < sliders + sizeof sliders / sizeof(ui_slider); s += 1) { + if(ui_slider_mouse_over(s, x, y)) { + s->value += dir * 0.05; + if(s->value < 0.0) s->value = 0.0; + if(s->value > 1.0) s->value = 1.0; + printf("Updated %p value to %f\n", s, s->value); + } + } + glutPostRedisplay(); +} + +void keyboardEvent(unsigned char c, int x, int y) { + if(c == '\e') { + glutLeaveMainLoop(); + exit(0); + } + if(c == 'a') { + glutPostRedisplay(); + } } int main(int argc, char** argv) { @@ -45,6 +93,8 @@ int main(int argc, char** argv) { glutCreateWindow("World of Cow"); glutDisplayFunc(display); glutMouseFunc(mouseEvent); + glutKeyboardFunc(keyboardEvent); + glutMouseWheelFunc(mouseWheelEvent); /* set projection and camera */ glMatrixMode(GL_PROJECTION); diff --git a/ui.c b/ui.c index c27879f..b217500 100644 --- a/ui.c +++ b/ui.c @@ -6,23 +6,32 @@ #include #include +#define BACK_COLOR 0.3, 0.35, 0.35 + void ui_button_draw(ui_button* b) { - printf("drawing button %p\n", b); int wWidth = glutGet(GLUT_WINDOW_WIDTH); int wHeight = glutGet(GLUT_WINDOW_HEIGHT); vec3 pos = vec3_add(b->position.absolute, vec3_new(b->position.relative.x * wWidth, b->position.relative.y * wHeight, 0.0)); vec3 ext = b->size; - glColor3f(1.0, 1.0, 1.0); + glColor3f(BACK_COLOR); glBegin(GL_QUADS); glVertexVec(pos); glVertex3f(pos.x + ext.x, pos.y, pos.z); glVertexVec(vec3_add(pos, ext)); glVertex3f(pos.x, pos.y + ext.y, pos.z); glEnd(); + glColor3f(0.7, 0.7, 0.8); + glLineWidth(2.0); + glBegin(GL_LINE_LOOP); + glVertexVec(pos); + glVertex3f(pos.x + ext.x, pos.y, pos.z); + glVertexVec(vec3_add(pos, ext)); + glVertex3f(pos.x, pos.y + ext.y, pos.z); + glEnd(); // Draw text if needed if(b->text != NULL) { - glColor3f(0.0, 0.0, 0.0); + glColor3f(1.0, 1.0, 1.0); // Get text size int textWidth = glutBitmapLength(GLUT_BITMAP_TIMES_ROMAN_24, (unsigned char*)b->text); int textHeight = glutBitmapHeight(GLUT_BITMAP_TIMES_ROMAN_24); @@ -35,13 +44,51 @@ void ui_button_draw(ui_button* b) { } } -char ui_button_mouse_over(ui_button* b) { - return 0; +char ui_button_mouse_over(ui_button* b, int mouseX, int mouseY) { + int wWidth = glutGet(GLUT_WINDOW_WIDTH); + int wHeight = glutGet(GLUT_WINDOW_HEIGHT); + + vec3 pos = vec3_add(b->position.absolute, vec3_new(b->position.relative.x * wWidth, b->position.relative.y * wHeight, 0.0)); + vec3 ext = b->size; + vec3 m = vec3_sub(vec3_new(mouseX, wHeight - mouseY, 0.0), pos); + return m.x > 0.0 && m.x < ext.x && m.y > 0.0 && m.y < ext.y; } void ui_slider_draw(ui_slider* s) { + int wWidth = glutGet(GLUT_WINDOW_WIDTH); + int wHeight = glutGet(GLUT_WINDOW_HEIGHT); + + vec3 pos = vec3_add(s->position.absolute, vec3_new(s->position.relative.x * wWidth, s->position.relative.y * wHeight, 0.0)); + vec3 ext = s->size; + + vec3 slider = vec3_add(pos, vec3_new(ext.x * s->value, ext.y * 0.5, 0.0)); + glBegin(GL_QUADS); + // draw background line + glColor3f(BACK_COLOR); + glVertexVec(pos); + glVertex3f(pos.x + ext.x, pos.y, pos.z); + glVertex3f(pos.x + ext.x, pos.y + ext.y, pos.z); + glVertex3f(pos.x, pos.y + ext.y, pos.z); + // Draw slider button thing + glColor3f(1.0, 1.0, 1.0); + glVertex3f(slider.x - ext.z, slider.y - ext.y, 0.0); + glVertex3f(slider.x + ext.z, slider.y - ext.y, 0.0); + glVertex3f(slider.x + ext.z, slider.y + ext.y, 0.0); + glVertex3f(slider.x - ext.z, slider.y + ext.y, 0.0); + + glEnd(); +} + +char ui_slider_mouse_over(ui_slider* s, int mouseX, int mouseY) { + int wWidth = glutGet(GLUT_WINDOW_WIDTH); + int wHeight = glutGet(GLUT_WINDOW_HEIGHT); + + vec3 pos = vec3_add(s->position.absolute, vec3_new(s->position.relative.x * wWidth, s->position.relative.y * wHeight, 0.0)); + vec3 ext = s->size; + vec3 m = vec3_sub(vec3_new(mouseX, wHeight - mouseY, 0.0), pos); + return m.x > 0.0 && m.x < ext.x && m.y > 0.0 && m.y < ext.y; +} + +void ui_slider_onclick(ui_slider* s, int mouseX, int mouseY, int button, int state) { } -char ui_slider_mouse_over(ui_slider* s) { - return 0; -} \ No newline at end of file diff --git a/ui.h b/ui.h index 3c6eca3..41e6225 100644 --- a/ui.h +++ b/ui.h @@ -11,7 +11,7 @@ typedef struct _ui_button { ui_pos position; /* x,y - width,height, z - unused */ vec3 size; // size in pixels - if screen is too small i am not sure if it is a smart idea to make everything smaller - void (*onClick); // instead of passing stuff in, im just gonna put every state variable in global scope to ensure everything lives... + void (*onClick)(); // instead of passing stuff in, im just gonna put every state variable in global scope to ensure everything lives... char* text; } ui_button; @@ -23,9 +23,10 @@ typedef struct _ui_slider { } ui_slider; void ui_button_draw(ui_button* b); -char ui_button_mouse_over(ui_button* b); +char ui_button_mouse_over(ui_button* b, int mouseX, int mouseY); void ui_slider_draw(ui_slider* s); -char ui_slider_mouse_over(ui_slider* s); +char ui_slider_mouse_over(ui_slider* s, int mouseX, int mouseY); +void ui_slider_onclick(ui_slider* s, int mouseX, int mouseY, int button, int state); #endif \ No newline at end of file