83d7fd058283614ca19008424d62e8313b388886
[vrlugburz] / tools / dunger / src / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <GL/glut.h>
5 #include <utk/cubertk.h>
6 #include <drawtext.h>
7 #include "level.h"
8 #include "lview.h"
9
10 static int init(void);
11 static void cleanup(void);
12 static void display(void);
13 static void reshape(int x, int y);
14 static void keyb(unsigned char key, int x, int y);
15 static void keyup(unsigned char key, int x, int y);
16 static void mouse(int bn, int st, int x, int y);
17 static void motion(int x, int y);
18
19 static void ucolor(int r, int g, int b, int a);
20 static void uclip(int x1, int y1, int x2, int y2);
21 static void uimage(int x, int y, const void *pix, int xsz, int ysz);
22 static void urect(int x1, int y1, int x2, int y2);
23 static void uline(int x1, int y1, int x2, int y2, int width);
24 static void utext(int x, int y, const char *txt, int sz);
25 static int utextspacing(void);
26 static int utextwidth(const char *txt, int sz);
27
28 static int parse_args(int argc, char **argv);
29
30
31 int win_width, win_height;
32 int view_width, view_height;
33 float view_panx, view_pany, view_zoom = 1.0f;
34
35 static int bnstate[8];
36 int mousex, mousey, clickx, clicky;
37
38 static float uiscale = 1.0f;
39 #define UISPLIT 150
40 int splitx;
41
42 #define FONTSZ  16
43 static struct dtx_font *uifont;
44 static utk_widget *uiroot;
45
46 static struct level *lvl;
47
48
49 int main(int argc, char **argv)
50 {
51         glutInit(&argc, argv);
52
53         if(parse_args(argc, argv) == -1) {
54                 return 1;
55         }
56
57         glutInitWindowSize(1280, 800);
58         glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE);
59         glutCreateWindow("dunger");
60
61         win_width = glutGet(GLUT_WINDOW_WIDTH);
62         win_height = glutGet(GLUT_WINDOW_HEIGHT);
63
64         glutDisplayFunc(display);
65         glutReshapeFunc(reshape);
66         glutKeyboardFunc(keyb);
67         glutKeyboardUpFunc(keyup);
68         glutMouseFunc(mouse);
69         glutMotionFunc(motion);
70         glutPassiveMotionFunc(motion);
71
72         if(init() == -1) {
73                 return 1;
74         }
75         atexit(cleanup);
76
77         glutMainLoop();
78         return 0;
79 }
80
81
82 static int init(void)
83 {
84         utk_widget *win;
85
86         glEnable(GL_MULTISAMPLE);
87
88         glClearColor(0.15, 0.15, 0.15, 1);
89
90         if(!(uifont = dtx_open_font("uifont.ttf", 0))) {
91                 fprintf(stderr, "failed to open uifont.ttf\n");
92                 return -1;
93         }
94         dtx_prepare_range(uifont, FONTSZ, ' ', 'z');
95         dtx_use_font(uifont, FONTSZ);
96
97         if(!(uiroot = utk_init(win_width / uiscale, win_height / uiscale))) {
98                 fprintf(stderr, "failed to initialized ubertk\n");
99                 return -1;
100         }
101         utk_set_color_func(ucolor);
102         utk_set_clip_func(uclip);
103         utk_set_image_func(uimage);
104         utk_set_rect_func(urect);
105         utk_set_line_func(uline);
106         utk_set_text_func(utext);
107         utk_set_text_spacing_func(utextspacing);
108         utk_set_text_width_func(utextwidth);
109
110         win = utk_vbox(uiroot, 0, UTK_DEF_SPACING);
111         utk_set_pos(win, 15, 15);
112         utk_button(win, "hello", 0, 0, 0, 0);
113         utk_button(win, "button 2", 0, 0, 0, 0);
114         utk_button(win, "button 3", 0, 0, 0, 0);
115
116         if(!(lvl = create_level(32, 32))) {
117                 fprintf(stderr, "failed to create level\n");
118                 return -1;
119         }
120         if(init_lview(lvl) == -1) {
121                 return -1;
122         }
123
124         splitx = UISPLIT * uiscale;
125         view_width = win_width - splitx;
126         view_height = win_height;
127
128         return 0;
129 }
130
131 static void cleanup(void)
132 {
133         destroy_lview();
134         free_level(lvl);
135         dtx_close_font(uifont);
136         utk_close(uiroot);
137 }
138
139 static void display(void)
140 {
141         glClear(GL_COLOR_BUFFER_BIT);
142
143         glMatrixMode(GL_MODELVIEW);
144         glLoadIdentity();
145
146         /* draw UI */
147
148         glMatrixMode(GL_PROJECTION);
149         glLoadIdentity();
150         glOrtho(0, splitx, win_height, 0, -1, 1);
151         glViewport(0, 0, splitx, win_height);
152
153         glBegin(GL_QUADS);
154         glColor3f(0.25, 0.25, 0.25);
155         glVertex2f(0, 0);
156         glVertex2f(splitx, 0);
157         glVertex2f(splitx, win_height);
158         glVertex2f(0, win_height);
159         glEnd();
160         utk_draw(uiroot);
161
162         /* draw view */
163
164         glMatrixMode(GL_PROJECTION);
165         glLoadIdentity();
166         glOrtho(0, view_width, 0, view_height, -1, 1);
167         glViewport(splitx, 0, view_width, view_height);
168
169         glBegin(GL_QUADS);
170         glColor3f(0.1, 0.1, 0.1);
171         glVertex2f(0, 0);
172         glVertex2f(view_width, 0);
173         glVertex2f(view_width, view_height);
174         glVertex2f(0, view_height);
175         glEnd();
176
177         draw_lview();
178
179         glutSwapBuffers();
180 }
181
182 static void reshape(int x, int y)
183 {
184         win_width = x;
185         win_height = y;
186
187         if(uiroot) {
188                 utk_set_size(uiroot, x / uiscale, y / uiscale);
189         }
190
191         lview_viewport(splitx, 0, x - splitx, y);
192 }
193
194 static void keyb(unsigned char key, int x, int y)
195 {
196         if(key == 27) exit(0);
197         utk_keyboard_event(key, 1);
198         glutPostRedisplay();
199 }
200
201 static void keyup(unsigned char key, int x, int y)
202 {
203         utk_keyboard_event(key, 0);
204         glutPostRedisplay();
205 }
206
207 static void mouse(int bn, int st, int x, int y)
208 {
209         int bidx = bn - GLUT_LEFT_BUTTON;
210         int press = st == GLUT_DOWN;
211
212         bnstate[bidx] = press;
213         mousex = x;
214         mousey = y;
215
216         if(bn <= 2) {
217                 if(press) {
218                         clickx = x;
219                         clicky = y;
220                 } else {
221                         clickx = clicky = -1;
222                 }
223         } else if(bn == 3) {
224                 if(press) view_zoom += 0.1;
225         } else if(bn == 4) {
226                 if(press) view_zoom -= 0.1;
227         }
228
229         lview_mbutton(bidx, press, x, y);
230
231         utk_mbutton_event(bidx, press, x / uiscale, y / uiscale);
232         glutPostRedisplay();
233 }
234
235 static void motion(int x, int y)
236 {
237         int dx, dy;
238         dx = x - mousex;
239         dy = y - mousey;
240         mousex = x;
241         mousey = y;
242
243         if(clickx >= splitx) {
244                 if(bnstate[1]) {
245                         view_panx -= dx;
246                         view_pany += dy;
247                 }
248         }
249
250         lview_mouse(x, y);
251
252         utk_mmotion_event(x / uiscale, y / uiscale);
253         glutPostRedisplay();
254 }
255
256 static int parse_args(int argc, char **argv)
257 {
258         int i;
259
260         for(i=1; i<argc; i++) {
261                 if(argv[i][0] == '-') {
262                         if(strcmp(argv[i], "-uiscale") == 0) {
263                                 if(!argv[++i] || !(uiscale = atoi(argv[i]))) {
264                                         fprintf(stderr, "-uiscale should be followed by a positive number\n");
265                                         return -1;
266                                 }
267                         } else if(strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "-h") == 0) {
268                                 printf("Usage: %s [options]\n", argv[0]);
269                                 printf("Options:\n");
270                                 printf(" -uiscale <scale>: UI scale factor (default: 1)\n");
271                                 printf(" -h,-help: print usage and exit\n");
272                                 exit(0);
273                         } else {
274                                 fprintf(stderr, "unknown option: %s\n", argv[i]);
275                                 return -1;
276                         }
277                 } else {
278                         fprintf(stderr, "unexpected argument: %s\n", argv[i]);
279                         return -1;
280                 }
281         }
282         return 0;
283 }
284
285 /* --- ubertk callbacks --- */
286
287 static void ucolor(int r, int g, int b, int a)
288 {
289         glColor4ub(r, g, b, a);
290 }
291
292 static void uclip(int x1, int y1, int x2, int y2)
293 {
294         if(!(x1 | y1 | x2 | y2)) {
295                 glDisable(GL_SCISSOR_TEST);
296         } else {
297                 glEnable(GL_SCISSOR_TEST);
298         }
299
300         x1 *= uiscale;
301         y1 *= uiscale;
302         x2 *= uiscale;
303         y2 *= uiscale;
304
305         glScissor(x1, win_height - y2, x2 - x1, y2 - y1);
306 }
307
308 static void uimage(int x, int y, const void *pix, int xsz, int ysz)
309 {
310         glPixelZoom(1, -1);
311         glRasterPos2f(x * uiscale, y * uiscale);
312         glDrawPixels(xsz, ysz, GL_BGRA, GL_UNSIGNED_BYTE, pix);
313 }
314
315 static void urect(int x1, int y1, int x2, int y2)
316 {
317         glRectf(x1 * uiscale, y1 * uiscale, x2 * uiscale, y2 * uiscale);
318 }
319
320 static void uline(int x1, int y1, int x2, int y2, int width)
321 {
322         glLineWidth(width);
323         glBegin(GL_LINES);
324         glVertex2f(x1 * uiscale, y1 * uiscale);
325         glVertex2f(x2 * uiscale, y2 * uiscale);
326         glEnd();
327 }
328
329 static void utext(int x, int y, const char *txt, int sz)
330 {
331         glMatrixMode(GL_PROJECTION);
332         glPushMatrix();
333         glTranslatef(x * uiscale, (y - dtx_baseline()) * uiscale, 0);
334         glScalef(uiscale, -uiscale, 1);
335
336         dtx_string(txt);
337         dtx_flush();
338
339         glPopMatrix();
340 }
341
342 static int utextspacing(void)
343 {
344         return dtx_line_height();
345 }
346
347 static int utextwidth(const char *txt, int sz)
348 {
349         return dtx_string_width(txt);
350 }