1 /*
2 Copyright 2012-2020 David Robillard <d@drobilla.net>
3
4 Permission to use, copy, modify, and/or distribute this software for any
5 purpose with or without fee is hereby granted, provided that the above
6 copyright notice and this permission notice appear in all copies.
7
8 THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include "test/test_utils.h"
18
19 #include "pugl/gl.h"
20 #include "pugl/pugl.h"
21
22 #include <stdbool.h>
23
24 static const int N_CURSORS = 7;
25 static const int N_ROWS = 2;
26 static const int N_COLS = 4;
27
28 typedef struct {
29 PuglWorld* world;
30 PuglTestOptions opts;
31 bool quit;
32 } PuglTestApp;
33
34 static void
onConfigure(const double width,const double height)35 onConfigure(const double width, const double height)
36 {
37 glEnable(GL_DEPTH_TEST);
38 glDepthFunc(GL_LESS);
39 glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
40
41 glMatrixMode(GL_PROJECTION);
42 glLoadIdentity();
43 glViewport(0, 0, (int)width, (int)height);
44 }
45
46 static void
onExpose(void)47 onExpose(void)
48 {
49 glMatrixMode(GL_MODELVIEW);
50 glLoadIdentity();
51
52 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
53 glColor3f(0.6f, 0.6f, 0.6f);
54
55 for (int row = 1; row < N_ROWS; ++row) {
56 const float y = (float)row * (2.0f / (float)N_ROWS) - 1.0f;
57 glBegin(GL_LINES);
58 glVertex2f(-1.0f, y);
59 glVertex2f(1.0f, y);
60 glEnd();
61 }
62
63 for (int col = 1; col < N_COLS; ++col) {
64 const float x = (float)col * (2.0f / (float)N_COLS) - 1.0f;
65 glBegin(GL_LINES);
66 glVertex2f(x, -1.0f);
67 glVertex2f(x, 1.0f);
68 glEnd();
69 }
70 }
71
72 static void
onMotion(PuglView * view,double x,double y)73 onMotion(PuglView* view, double x, double y)
74 {
75 const PuglRect frame = puglGetFrame(view);
76 int row = (int)(y * N_ROWS / frame.height);
77 int col = (int)(x * N_COLS / frame.width);
78
79 row = (row < 0) ? 0 : (row >= N_ROWS) ? (N_ROWS - 1) : row;
80 col = (col < 0) ? 0 : (col >= N_COLS) ? (N_COLS - 1) : col;
81
82 const PuglCursor cursor = (PuglCursor)((row * N_COLS + col) % N_CURSORS);
83 puglSetCursor(view, cursor);
84 }
85
86 static PuglStatus
onEvent(PuglView * view,const PuglEvent * event)87 onEvent(PuglView* view, const PuglEvent* event)
88 {
89 PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
90
91 printEvent(event, "Event: ", app->opts.verbose);
92
93 switch (event->type) {
94 case PUGL_CONFIGURE:
95 onConfigure(event->configure.width, event->configure.height);
96 break;
97 case PUGL_KEY_PRESS:
98 if (event->key.key == 'q' || event->key.key == PUGL_KEY_ESCAPE) {
99 app->quit = 1;
100 }
101 break;
102 case PUGL_MOTION:
103 onMotion(view, event->motion.x, event->motion.y);
104 break;
105 case PUGL_EXPOSE:
106 onExpose();
107 break;
108 case PUGL_POINTER_OUT:
109 puglSetCursor(view, PUGL_CURSOR_ARROW);
110 break;
111 case PUGL_CLOSE:
112 app->quit = 1;
113 break;
114 default:
115 break;
116 }
117
118 return PUGL_SUCCESS;
119 }
120
121 int
main(int argc,char ** argv)122 main(int argc, char** argv)
123 {
124 PuglTestApp app = {0};
125
126 app.opts = puglParseTestOptions(&argc, &argv);
127 if (app.opts.help) {
128 puglPrintTestUsage(argv[0], "");
129 return 1;
130 }
131
132 app.world = puglNewWorld(PUGL_PROGRAM, 0);
133
134 puglSetWorldHandle(app.world, &app);
135 puglSetClassName(app.world, "Pugl Test");
136
137 PuglView* view = puglNewView(app.world);
138
139 puglSetWindowTitle(view, "Pugl Window Demo");
140 puglSetDefaultSize(view, 512, 256);
141 puglSetMinSize(view, 128, 64);
142 puglSetBackend(view, puglGlBackend());
143
144 puglSetViewHint(view, PUGL_USE_DEBUG_CONTEXT, app.opts.errorChecking);
145 puglSetViewHint(view, PUGL_RESIZABLE, app.opts.resizable);
146 puglSetViewHint(view, PUGL_SAMPLES, app.opts.samples);
147 puglSetViewHint(view, PUGL_DOUBLE_BUFFER, app.opts.doubleBuffer);
148 puglSetViewHint(view, PUGL_SWAP_INTERVAL, app.opts.sync);
149 puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, app.opts.ignoreKeyRepeat);
150 puglSetHandle(view, &app);
151 puglSetEventFunc(view, onEvent);
152
153 const PuglStatus st = puglRealize(view);
154 if (st) {
155 return logError("Failed to create window (%s)\n", puglStrerror(st));
156 }
157
158 puglShow(view);
159
160 while (!app.quit) {
161 puglUpdate(app.world, -1.0);
162 }
163
164 puglFreeView(view);
165 puglFreeWorld(app.world);
166
167 return 0;
168 }
169