From 41373723a1cea45f08d59830022404defbd43332 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 23 Jul 2019 19:24:39 +0200 Subject: Test: Move test programs to a subdirectory --- pugl_cairo_test.c | 206 ----------------------------- pugl_test.c | 349 ------------------------------------------------- test/pugl_cairo_test.c | 206 +++++++++++++++++++++++++++++ test/pugl_test.c | 349 +++++++++++++++++++++++++++++++++++++++++++++++++ wscript | 2 +- 5 files changed, 556 insertions(+), 556 deletions(-) delete mode 100644 pugl_cairo_test.c delete mode 100644 pugl_test.c create mode 100644 test/pugl_cairo_test.c create mode 100644 test/pugl_test.c diff --git a/pugl_cairo_test.c b/pugl_cairo_test.c deleted file mode 100644 index 524e8b0..0000000 --- a/pugl_cairo_test.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - Copyright 2012-2019 David Robillard - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/** - @file pugl_cairo_test.c A simple Pugl test that creates a top-level window. -*/ - -#include "pugl/pugl.h" - -#include - -#include -#include -#include - -static int quit = 0; -static bool entered = false; - -typedef struct { - int x; - int y; - int w; - int h; - bool pressed; - const char* label; -} Button; - -static Button toggle_button = { 16, 16, 128, 64, false, "Test" }; - -static void -roundedBox(cairo_t* cr, double x, double y, double w, double h) -{ - static const double radius = 10; - static const double degrees = 3.14159265 / 180.0; - - cairo_new_sub_path(cr); - cairo_arc(cr, - x + w - radius, - y + radius, - radius, -90 * degrees, 0 * degrees); - cairo_arc(cr, - x + w - radius, y + h - radius, - radius, 0 * degrees, 90 * degrees); - cairo_arc(cr, - x + radius, y + h - radius, - radius, 90 * degrees, 180 * degrees); - cairo_arc(cr, - x + radius, y + radius, - radius, 180 * degrees, 270 * degrees); - cairo_close_path(cr); -} - -static void -buttonDraw(cairo_t* cr, const Button* but) -{ - // Draw base - if (but->pressed) { - cairo_set_source_rgba(cr, 0.4, 0.9, 0.1, 1); - } else { - cairo_set_source_rgba(cr, 0.3, 0.5, 0.1, 1); - } - roundedBox(cr, but->x, but->y, but->w, but->h); - cairo_fill_preserve(cr); - - // Draw border - cairo_set_source_rgba(cr, 0.4, 0.9, 0.1, 1); - cairo_set_line_width(cr, 4.0); - cairo_stroke(cr); - - // Draw label - cairo_text_extents_t extents; - cairo_set_font_size(cr, 32.0); - cairo_text_extents(cr, but->label, &extents); - cairo_move_to(cr, - (but->x + but->w / 2.0) - extents.width / 2, - (but->y + but->h / 2.0) + extents.height / 2); - cairo_set_source_rgba(cr, 0, 0, 0, 1); - cairo_show_text(cr, but->label); -} - -static bool -buttonTouches(const Button* but, double x, double y) -{ - return (x >= toggle_button.x && x <= toggle_button.x + toggle_button.w && - y >= toggle_button.y && y <= toggle_button.y + toggle_button.h); -} - -static void -onDisplay(PuglView* view) -{ - cairo_t* cr = puglGetContext(view); - - // Draw background - int width, height; - puglGetSize(view, &width, &height); - if (entered) { - cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); - } else { - cairo_set_source_rgb(cr, 0, 0, 0); - } - cairo_rectangle(cr, 0, 0, width, height); - cairo_fill(cr); - - // Draw button - buttonDraw(cr, &toggle_button); -} - -static void -onClose(PuglView* view) -{ - quit = 1; -} - -static void -onEvent(PuglView* view, const PuglEvent* event) -{ - switch (event->type) { - case PUGL_KEY_PRESS: - if (event->key.character == 'q' || - event->key.character == 'Q' || - event->key.character == PUGL_CHAR_ESCAPE) { - quit = 1; - } - break; - case PUGL_BUTTON_PRESS: - if (buttonTouches(&toggle_button, event->button.x, event->button.y)) { - toggle_button.pressed = !toggle_button.pressed; - puglPostRedisplay(view); - } - break; - case PUGL_ENTER_NOTIFY: - entered = true; - puglPostRedisplay(view); - break; - case PUGL_LEAVE_NOTIFY: - entered = false; - puglPostRedisplay(view); - break; - case PUGL_EXPOSE: - onDisplay(view); - break; - case PUGL_CLOSE: - onClose(view); - break; - default: break; - } -} - -int -main(int argc, char** argv) -{ - bool ignoreKeyRepeat = false; - bool resizable = false; - for (int i = 1; i < argc; ++i) { - if (!strcmp(argv[i], "-h")) { - printf("USAGE: %s [OPTIONS]...\n\n" - " -h Display this help\n" - " -i Ignore key repeat\n" - " -r Resizable window\n", argv[0]); - return 0; - } else if (!strcmp(argv[i], "-i")) { - ignoreKeyRepeat = true; - } else if (!strcmp(argv[i], "-r")) { - resizable = true; - } else { - fprintf(stderr, "Unknown option: %s\n", argv[i]); - } - } - - PuglView* view = puglInit(NULL, NULL); - puglInitWindowClass(view, "PuglCairoTest"); - puglInitWindowSize(view, 512, 512); - puglInitWindowMinSize(view, 256, 256); - puglInitResizable(view, resizable); - puglInitContextType(view, PUGL_CAIRO); - - puglIgnoreKeyRepeat(view, ignoreKeyRepeat); - puglSetEventFunc(view, onEvent); - - if (puglCreateWindow(view, "Pugl Test")) { - return 1; - } - - puglShowWindow(view); - - while (!quit) { - puglWaitForEvent(view); - puglProcessEvents(view); - } - - puglDestroy(view); - return 0; -} diff --git a/pugl_test.c b/pugl_test.c deleted file mode 100644 index 866e3c2..0000000 --- a/pugl_test.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - Copyright 2012-2019 David Robillard - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/** - @file pugl_test.c A simple Pugl test that creates a top-level window. -*/ - -#define GL_SILENCE_DEPRECATION 1 - -#include "pugl/gl.h" -#include "pugl/pugl.h" - -#include -#include -#include -#include - -static bool continuous = false; -static int quit = 0; -static float xAngle = 0.0f; -static float yAngle = 0.0f; -static float dist = 10.0f; -static double lastMouseX = 0.0; -static double lastMouseY = 0.0; -static float lastDrawTime = 0.0; -static unsigned framesDrawn = 0; -static bool mouseEntered = false; - -static const float cubeVertices[] = { - -1.0f, -1.0f, -1.0f, - -1.0f, -1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, - - 1.0f, 1.0f, -1.0f, - -1.0f, -1.0f, -1.0f, - -1.0f, 1.0f, -1.0f, - - 1.0f, -1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, - - 1.0f, 1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, - -1.0f, -1.0f, -1.0f, - - -1.0f, -1.0f, -1.0f, - -1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, -1.0f, - - 1.0f, -1.0f, 1.0f, - -1.0f, -1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, - - -1.0f, 1.0f, 1.0f, - -1.0f, -1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, - - 1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, - 1.0f, 1.0f, -1.0f, - - 1.0f, -1.0f, -1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, - - 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, -1.0f, - -1.0f, 1.0f, -1.0f, - - 1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, -1.0f, - -1.0f, 1.0f, 1.0f, - - 1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f -}; - -/** Calculate a projection matrix for a given perspective. */ -static void -perspective(float* m, float fov, float aspect, float zNear, float zFar) -{ - const float h = tanf(fov); - const float w = h / aspect; - const float depth = zNear - zFar; - const float q = (zFar + zNear) / depth; - const float qn = 2 * zFar * zNear / depth; - - m[0] = w; m[1] = 0; m[2] = 0; m[3] = 0; - m[4] = 0; m[5] = h; m[6] = 0; m[7] = 0; - m[8] = 0; m[9] = 0; m[10] = q; m[11] = -1; - m[12] = 0; m[13] = 0; m[14] = qn; m[15] = 0; -} - -static void -onReshape(PuglView* view, int width, int height) -{ - (void)view; - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glViewport(0, 0, width, height); - - float projection[16]; - perspective(projection, 1.8f, width / (float)height, 1.0, 100.0f); - glLoadMatrixf(projection); -} - -static void -onDisplay(PuglView* view) -{ - const float thisTime = (float)puglGetTime(view); - if (continuous) { - xAngle = fmodf(xAngle + (thisTime - lastDrawTime) * 100.0f, 360.0f); - yAngle = fmodf(yAngle + (thisTime - lastDrawTime) * 100.0f, 360.0f); - } - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0.0f, 0.0f, dist * -1); - glRotatef(xAngle, 0.0f, 1.0f, 0.0f); - glRotatef(yAngle, 1.0f, 0.0f, 0.0f); - - const float bg = mouseEntered ? 0.2f : 0.0f; - glClearColor(bg, bg, bg, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - - glVertexPointer(3, GL_FLOAT, 0, cubeVertices); - glColorPointer(3, GL_FLOAT, 0, cubeVertices); - glDrawArrays(GL_TRIANGLES, 0, 12 * 3); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - - lastDrawTime = thisTime; - ++framesDrawn; -} - -static int -printModifiers(const uint32_t mods) -{ - return fprintf(stderr, "Modifiers:%s%s%s%s\n", - (mods & PUGL_MOD_SHIFT) ? " Shift" : "", - (mods & PUGL_MOD_CTRL) ? " Ctrl" : "", - (mods & PUGL_MOD_ALT) ? " Alt" : "", - (mods & PUGL_MOD_SUPER) ? " Super" : ""); -} - -static int -printEvent(const PuglEvent* event, const char* prefix) -{ - switch (event->type) { - case PUGL_KEY_PRESS: - return fprintf(stderr, "%sKey %u (char U+%04X special U+%04X) press (%s)%s\n", - prefix, - event->key.keycode, event->key.character, event->key.special, - event->key.utf8, event->key.filter ? " (filtered)" : ""); - - case PUGL_KEY_RELEASE: - return fprintf(stderr, "%sKey %u (char U+%04X special U+%04X) release (%s)%s\n", - prefix, - event->key.keycode, event->key.character, event->key.special, - event->key.utf8, event->key.filter ? " (filtered)" : ""); - case PUGL_BUTTON_PRESS: - case PUGL_BUTTON_RELEASE: - return (fprintf(stderr, "%sMouse %d %s at %f,%f ", - prefix, - event->button.button, - (event->type == PUGL_BUTTON_PRESS) ? "down" : "up", - event->button.x, - event->button.y) + - printModifiers(event->scroll.state)); - case PUGL_SCROLL: - return (fprintf(stderr, "%sScroll %f %f %f %f ", - prefix, - event->scroll.x, event->scroll.y, - event->scroll.dx, event->scroll.dy) + - printModifiers(event->scroll.state)); - case PUGL_ENTER_NOTIFY: - return fprintf(stderr, "%sMouse enter at %f,%f\n", - prefix, event->crossing.x, event->crossing.y); - case PUGL_LEAVE_NOTIFY: - return fprintf(stderr, "%sMouse leave at %f,%f\n", - prefix, event->crossing.x, event->crossing.y); - case PUGL_FOCUS_IN: - return fprintf(stderr, "%sFocus in%s\n", - prefix, event->focus.grab ? " (grab)" : ""); - case PUGL_FOCUS_OUT: - return fprintf(stderr, "%sFocus out%s\n", - prefix, event->focus.grab ? " (ungrab)" : ""); - default: break; - } - - return 0; -} - -static void -onEvent(PuglView* view, const PuglEvent* event) -{ - printEvent(event, "Event: "); - - switch (event->type) { - case PUGL_CONFIGURE: - onReshape(view, (int)event->configure.width, (int)event->configure.height); - break; - case PUGL_EXPOSE: - onDisplay(view); - break; - case PUGL_CLOSE: - quit = 1; - break; - case PUGL_KEY_PRESS: - if (event->key.character == 'q' || - event->key.character == 'Q' || - event->key.character == PUGL_CHAR_ESCAPE) { - quit = 1; - } - break; - case PUGL_MOTION_NOTIFY: - xAngle = fmodf(xAngle - (float)(event->motion.x - lastMouseX), 360.0f); - yAngle = fmodf(yAngle + (float)(event->motion.y - lastMouseY), 360.0f); - lastMouseX = event->motion.x; - lastMouseY = event->motion.y; - puglPostRedisplay(view); - break; - case PUGL_SCROLL: - dist += (float)event->scroll.dy; - if (dist < 10.0f) { - dist = 10.0f; - } - puglPostRedisplay(view); - break; - case PUGL_ENTER_NOTIFY: - mouseEntered = true; - break; - case PUGL_LEAVE_NOTIFY: - mouseEntered = false; - break; - default: - break; - } -} - -int -main(int argc, char** argv) -{ - int samples = 0; - int doubleBuffer = PUGL_FALSE; - bool ignoreKeyRepeat = false; - bool resizable = false; - for (int i = 1; i < argc; ++i) { - if (!strcmp(argv[i], "-a")) { - samples = 4; - } else if (!strcmp(argv[i], "-c")) { - continuous = true; - } else if (!strcmp(argv[i], "-d")) { - doubleBuffer = PUGL_TRUE; - } else if (!strcmp(argv[i], "-h")) { - printf("USAGE: %s [OPTIONS]...\n\n" - " -a Enable anti-aliasing\n" - " -c Continuously animate and draw\n" - " -d Enable double-buffering\n" - " -h Display this help\n" - " -i Ignore key repeat\n" - " -r Resizable window\n", argv[0]); - return 0; - } else if (!strcmp(argv[i], "-i")) { - ignoreKeyRepeat = true; - } else if (!strcmp(argv[i], "-r")) { - resizable = true; - } else { - fprintf(stderr, "Unknown option: %s\n", argv[i]); - } - } - - setlocale(LC_CTYPE, ""); - - PuglView* view = puglInit(NULL, NULL); - puglInitWindowClass(view, "PuglTest"); - puglInitWindowSize(view, 512, 512); - puglInitWindowMinSize(view, 256, 256); - puglInitWindowAspectRatio(view, 1, 1, 1, 1); - puglInitResizable(view, resizable); - - puglInitWindowHint(view, PUGL_SAMPLES, samples); - puglInitWindowHint(view, PUGL_DOUBLE_BUFFER, doubleBuffer); - - puglIgnoreKeyRepeat(view, ignoreKeyRepeat); - puglSetEventFunc(view, onEvent); - - if (puglCreateWindow(view, "Pugl Test")) { - return 1; - } - - puglEnterContext(view); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glClearColor(0.2f, 0.2f, 0.2f, 1.0f); - puglLeaveContext(view, false); - - puglShowWindow(view); - - float lastReportTime = (float)puglGetTime(view); - bool requestedAttention = false; - while (!quit) { - const float thisTime = (float)puglGetTime(view); - - if (continuous) { - puglPostRedisplay(view); - } else { - puglWaitForEvent(view); - } - - puglProcessEvents(view); - - if (!requestedAttention && thisTime > 5) { - puglRequestAttention(view); - requestedAttention = true; - } - - if (continuous && thisTime > lastReportTime + 5) { - const double fps = framesDrawn / (thisTime - lastReportTime); - fprintf(stderr, - "%u frames in %.0f seconds = %.3f FPS\n", - framesDrawn, thisTime - lastReportTime, fps); - - lastReportTime = thisTime; - framesDrawn = 0; - } - } - - puglDestroy(view); - return 0; -} diff --git a/test/pugl_cairo_test.c b/test/pugl_cairo_test.c new file mode 100644 index 0000000..524e8b0 --- /dev/null +++ b/test/pugl_cairo_test.c @@ -0,0 +1,206 @@ +/* + Copyright 2012-2019 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file pugl_cairo_test.c A simple Pugl test that creates a top-level window. +*/ + +#include "pugl/pugl.h" + +#include + +#include +#include +#include + +static int quit = 0; +static bool entered = false; + +typedef struct { + int x; + int y; + int w; + int h; + bool pressed; + const char* label; +} Button; + +static Button toggle_button = { 16, 16, 128, 64, false, "Test" }; + +static void +roundedBox(cairo_t* cr, double x, double y, double w, double h) +{ + static const double radius = 10; + static const double degrees = 3.14159265 / 180.0; + + cairo_new_sub_path(cr); + cairo_arc(cr, + x + w - radius, + y + radius, + radius, -90 * degrees, 0 * degrees); + cairo_arc(cr, + x + w - radius, y + h - radius, + radius, 0 * degrees, 90 * degrees); + cairo_arc(cr, + x + radius, y + h - radius, + radius, 90 * degrees, 180 * degrees); + cairo_arc(cr, + x + radius, y + radius, + radius, 180 * degrees, 270 * degrees); + cairo_close_path(cr); +} + +static void +buttonDraw(cairo_t* cr, const Button* but) +{ + // Draw base + if (but->pressed) { + cairo_set_source_rgba(cr, 0.4, 0.9, 0.1, 1); + } else { + cairo_set_source_rgba(cr, 0.3, 0.5, 0.1, 1); + } + roundedBox(cr, but->x, but->y, but->w, but->h); + cairo_fill_preserve(cr); + + // Draw border + cairo_set_source_rgba(cr, 0.4, 0.9, 0.1, 1); + cairo_set_line_width(cr, 4.0); + cairo_stroke(cr); + + // Draw label + cairo_text_extents_t extents; + cairo_set_font_size(cr, 32.0); + cairo_text_extents(cr, but->label, &extents); + cairo_move_to(cr, + (but->x + but->w / 2.0) - extents.width / 2, + (but->y + but->h / 2.0) + extents.height / 2); + cairo_set_source_rgba(cr, 0, 0, 0, 1); + cairo_show_text(cr, but->label); +} + +static bool +buttonTouches(const Button* but, double x, double y) +{ + return (x >= toggle_button.x && x <= toggle_button.x + toggle_button.w && + y >= toggle_button.y && y <= toggle_button.y + toggle_button.h); +} + +static void +onDisplay(PuglView* view) +{ + cairo_t* cr = puglGetContext(view); + + // Draw background + int width, height; + puglGetSize(view, &width, &height); + if (entered) { + cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); + } else { + cairo_set_source_rgb(cr, 0, 0, 0); + } + cairo_rectangle(cr, 0, 0, width, height); + cairo_fill(cr); + + // Draw button + buttonDraw(cr, &toggle_button); +} + +static void +onClose(PuglView* view) +{ + quit = 1; +} + +static void +onEvent(PuglView* view, const PuglEvent* event) +{ + switch (event->type) { + case PUGL_KEY_PRESS: + if (event->key.character == 'q' || + event->key.character == 'Q' || + event->key.character == PUGL_CHAR_ESCAPE) { + quit = 1; + } + break; + case PUGL_BUTTON_PRESS: + if (buttonTouches(&toggle_button, event->button.x, event->button.y)) { + toggle_button.pressed = !toggle_button.pressed; + puglPostRedisplay(view); + } + break; + case PUGL_ENTER_NOTIFY: + entered = true; + puglPostRedisplay(view); + break; + case PUGL_LEAVE_NOTIFY: + entered = false; + puglPostRedisplay(view); + break; + case PUGL_EXPOSE: + onDisplay(view); + break; + case PUGL_CLOSE: + onClose(view); + break; + default: break; + } +} + +int +main(int argc, char** argv) +{ + bool ignoreKeyRepeat = false; + bool resizable = false; + for (int i = 1; i < argc; ++i) { + if (!strcmp(argv[i], "-h")) { + printf("USAGE: %s [OPTIONS]...\n\n" + " -h Display this help\n" + " -i Ignore key repeat\n" + " -r Resizable window\n", argv[0]); + return 0; + } else if (!strcmp(argv[i], "-i")) { + ignoreKeyRepeat = true; + } else if (!strcmp(argv[i], "-r")) { + resizable = true; + } else { + fprintf(stderr, "Unknown option: %s\n", argv[i]); + } + } + + PuglView* view = puglInit(NULL, NULL); + puglInitWindowClass(view, "PuglCairoTest"); + puglInitWindowSize(view, 512, 512); + puglInitWindowMinSize(view, 256, 256); + puglInitResizable(view, resizable); + puglInitContextType(view, PUGL_CAIRO); + + puglIgnoreKeyRepeat(view, ignoreKeyRepeat); + puglSetEventFunc(view, onEvent); + + if (puglCreateWindow(view, "Pugl Test")) { + return 1; + } + + puglShowWindow(view); + + while (!quit) { + puglWaitForEvent(view); + puglProcessEvents(view); + } + + puglDestroy(view); + return 0; +} diff --git a/test/pugl_test.c b/test/pugl_test.c new file mode 100644 index 0000000..866e3c2 --- /dev/null +++ b/test/pugl_test.c @@ -0,0 +1,349 @@ +/* + Copyright 2012-2019 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file pugl_test.c A simple Pugl test that creates a top-level window. +*/ + +#define GL_SILENCE_DEPRECATION 1 + +#include "pugl/gl.h" +#include "pugl/pugl.h" + +#include +#include +#include +#include + +static bool continuous = false; +static int quit = 0; +static float xAngle = 0.0f; +static float yAngle = 0.0f; +static float dist = 10.0f; +static double lastMouseX = 0.0; +static double lastMouseY = 0.0; +static float lastDrawTime = 0.0; +static unsigned framesDrawn = 0; +static bool mouseEntered = false; + +static const float cubeVertices[] = { + -1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + + 1.0f, 1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + + 1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + + 1.0f, 1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, + + -1.0f, -1.0f, -1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, -1.0f, + + 1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, + + -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, + + 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, + + 1.0f, -1.0f, -1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, + + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + + 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, 1.0f, + + 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f +}; + +/** Calculate a projection matrix for a given perspective. */ +static void +perspective(float* m, float fov, float aspect, float zNear, float zFar) +{ + const float h = tanf(fov); + const float w = h / aspect; + const float depth = zNear - zFar; + const float q = (zFar + zNear) / depth; + const float qn = 2 * zFar * zNear / depth; + + m[0] = w; m[1] = 0; m[2] = 0; m[3] = 0; + m[4] = 0; m[5] = h; m[6] = 0; m[7] = 0; + m[8] = 0; m[9] = 0; m[10] = q; m[11] = -1; + m[12] = 0; m[13] = 0; m[14] = qn; m[15] = 0; +} + +static void +onReshape(PuglView* view, int width, int height) +{ + (void)view; + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glViewport(0, 0, width, height); + + float projection[16]; + perspective(projection, 1.8f, width / (float)height, 1.0, 100.0f); + glLoadMatrixf(projection); +} + +static void +onDisplay(PuglView* view) +{ + const float thisTime = (float)puglGetTime(view); + if (continuous) { + xAngle = fmodf(xAngle + (thisTime - lastDrawTime) * 100.0f, 360.0f); + yAngle = fmodf(yAngle + (thisTime - lastDrawTime) * 100.0f, 360.0f); + } + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0f, 0.0f, dist * -1); + glRotatef(xAngle, 0.0f, 1.0f, 0.0f); + glRotatef(yAngle, 1.0f, 0.0f, 0.0f); + + const float bg = mouseEntered ? 0.2f : 0.0f; + glClearColor(bg, bg, bg, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, cubeVertices); + glColorPointer(3, GL_FLOAT, 0, cubeVertices); + glDrawArrays(GL_TRIANGLES, 0, 12 * 3); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + lastDrawTime = thisTime; + ++framesDrawn; +} + +static int +printModifiers(const uint32_t mods) +{ + return fprintf(stderr, "Modifiers:%s%s%s%s\n", + (mods & PUGL_MOD_SHIFT) ? " Shift" : "", + (mods & PUGL_MOD_CTRL) ? " Ctrl" : "", + (mods & PUGL_MOD_ALT) ? " Alt" : "", + (mods & PUGL_MOD_SUPER) ? " Super" : ""); +} + +static int +printEvent(const PuglEvent* event, const char* prefix) +{ + switch (event->type) { + case PUGL_KEY_PRESS: + return fprintf(stderr, "%sKey %u (char U+%04X special U+%04X) press (%s)%s\n", + prefix, + event->key.keycode, event->key.character, event->key.special, + event->key.utf8, event->key.filter ? " (filtered)" : ""); + + case PUGL_KEY_RELEASE: + return fprintf(stderr, "%sKey %u (char U+%04X special U+%04X) release (%s)%s\n", + prefix, + event->key.keycode, event->key.character, event->key.special, + event->key.utf8, event->key.filter ? " (filtered)" : ""); + case PUGL_BUTTON_PRESS: + case PUGL_BUTTON_RELEASE: + return (fprintf(stderr, "%sMouse %d %s at %f,%f ", + prefix, + event->button.button, + (event->type == PUGL_BUTTON_PRESS) ? "down" : "up", + event->button.x, + event->button.y) + + printModifiers(event->scroll.state)); + case PUGL_SCROLL: + return (fprintf(stderr, "%sScroll %f %f %f %f ", + prefix, + event->scroll.x, event->scroll.y, + event->scroll.dx, event->scroll.dy) + + printModifiers(event->scroll.state)); + case PUGL_ENTER_NOTIFY: + return fprintf(stderr, "%sMouse enter at %f,%f\n", + prefix, event->crossing.x, event->crossing.y); + case PUGL_LEAVE_NOTIFY: + return fprintf(stderr, "%sMouse leave at %f,%f\n", + prefix, event->crossing.x, event->crossing.y); + case PUGL_FOCUS_IN: + return fprintf(stderr, "%sFocus in%s\n", + prefix, event->focus.grab ? " (grab)" : ""); + case PUGL_FOCUS_OUT: + return fprintf(stderr, "%sFocus out%s\n", + prefix, event->focus.grab ? " (ungrab)" : ""); + default: break; + } + + return 0; +} + +static void +onEvent(PuglView* view, const PuglEvent* event) +{ + printEvent(event, "Event: "); + + switch (event->type) { + case PUGL_CONFIGURE: + onReshape(view, (int)event->configure.width, (int)event->configure.height); + break; + case PUGL_EXPOSE: + onDisplay(view); + break; + case PUGL_CLOSE: + quit = 1; + break; + case PUGL_KEY_PRESS: + if (event->key.character == 'q' || + event->key.character == 'Q' || + event->key.character == PUGL_CHAR_ESCAPE) { + quit = 1; + } + break; + case PUGL_MOTION_NOTIFY: + xAngle = fmodf(xAngle - (float)(event->motion.x - lastMouseX), 360.0f); + yAngle = fmodf(yAngle + (float)(event->motion.y - lastMouseY), 360.0f); + lastMouseX = event->motion.x; + lastMouseY = event->motion.y; + puglPostRedisplay(view); + break; + case PUGL_SCROLL: + dist += (float)event->scroll.dy; + if (dist < 10.0f) { + dist = 10.0f; + } + puglPostRedisplay(view); + break; + case PUGL_ENTER_NOTIFY: + mouseEntered = true; + break; + case PUGL_LEAVE_NOTIFY: + mouseEntered = false; + break; + default: + break; + } +} + +int +main(int argc, char** argv) +{ + int samples = 0; + int doubleBuffer = PUGL_FALSE; + bool ignoreKeyRepeat = false; + bool resizable = false; + for (int i = 1; i < argc; ++i) { + if (!strcmp(argv[i], "-a")) { + samples = 4; + } else if (!strcmp(argv[i], "-c")) { + continuous = true; + } else if (!strcmp(argv[i], "-d")) { + doubleBuffer = PUGL_TRUE; + } else if (!strcmp(argv[i], "-h")) { + printf("USAGE: %s [OPTIONS]...\n\n" + " -a Enable anti-aliasing\n" + " -c Continuously animate and draw\n" + " -d Enable double-buffering\n" + " -h Display this help\n" + " -i Ignore key repeat\n" + " -r Resizable window\n", argv[0]); + return 0; + } else if (!strcmp(argv[i], "-i")) { + ignoreKeyRepeat = true; + } else if (!strcmp(argv[i], "-r")) { + resizable = true; + } else { + fprintf(stderr, "Unknown option: %s\n", argv[i]); + } + } + + setlocale(LC_CTYPE, ""); + + PuglView* view = puglInit(NULL, NULL); + puglInitWindowClass(view, "PuglTest"); + puglInitWindowSize(view, 512, 512); + puglInitWindowMinSize(view, 256, 256); + puglInitWindowAspectRatio(view, 1, 1, 1, 1); + puglInitResizable(view, resizable); + + puglInitWindowHint(view, PUGL_SAMPLES, samples); + puglInitWindowHint(view, PUGL_DOUBLE_BUFFER, doubleBuffer); + + puglIgnoreKeyRepeat(view, ignoreKeyRepeat); + puglSetEventFunc(view, onEvent); + + if (puglCreateWindow(view, "Pugl Test")) { + return 1; + } + + puglEnterContext(view); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glClearColor(0.2f, 0.2f, 0.2f, 1.0f); + puglLeaveContext(view, false); + + puglShowWindow(view); + + float lastReportTime = (float)puglGetTime(view); + bool requestedAttention = false; + while (!quit) { + const float thisTime = (float)puglGetTime(view); + + if (continuous) { + puglPostRedisplay(view); + } else { + puglWaitForEvent(view); + } + + puglProcessEvents(view); + + if (!requestedAttention && thisTime > 5) { + puglRequestAttention(view); + requestedAttention = true; + } + + if (continuous && thisTime > lastReportTime + 5) { + const double fps = framesDrawn / (thisTime - lastReportTime); + fprintf(stderr, + "%u frames in %.0f seconds = %.3f FPS\n", + framesDrawn, thisTime - lastReportTime, fps); + + lastReportTime = thisTime; + framesDrawn = 0; + } + } + + puglDestroy(view); + return 0; +} diff --git a/wscript b/wscript index 09a8296..99c2fad 100644 --- a/wscript +++ b/wscript @@ -159,7 +159,7 @@ def build(bld): target = prog bld(features = 'c cprogram', - source = '%s.c' % prog, + source = 'test/%s.c' % prog, use = 'libpugl_static', lib = test_libs, target = target, -- cgit v1.2.1