5 #include <utk/cubertk.h>
11 static int init(void);
12 static void cleanup(void);
13 static void display(void);
14 static void reshape(int x, int y);
15 static void keyb(unsigned char key, int x, int y);
16 static void keyup(unsigned char key, int x, int y);
17 static void mouse(int bn, int st, int x, int y);
18 static void motion(int x, int y);
20 static void cb_new(utk_event *ev, void *data);
21 static void cb_new_ok(utk_event *ev, void *data);
22 static void cb_open(utk_event *ev, void *data);
23 static void cb_open_ok(utk_event *ev, void *data);
24 static void cb_save(utk_event *ev, void *data);
25 static void cb_save_ok(utk_event *ev, void *data);
27 static void cb_cancel(utk_event *ev, void *data);
29 static void cb_toolselect(utk_event *ev, void *data);
31 static int parse_args(int argc, char **argv);
34 static void ucolor(int r, int g, int b, int a);
35 static void uclip(int x1, int y1, int x2, int y2);
36 static void uimage(int x, int y, const void *pix, int xsz, int ysz);
37 static void urect(int x1, int y1, int x2, int y2);
38 static void uline(int x1, int y1, int x2, int y2, int width);
39 static void utext(int x, int y, const char *txt, int sz);
40 static int utextspacing(void);
41 static int utextwidth(const char *txt, int sz);
44 int win_width, win_height;
45 int view_width, view_height;
46 float view_panx, view_pany, view_zoom = 1.0f;
48 static int bnstate[8];
49 int mousex, mousey, clickx, clicky;
51 static float uiscale = 1.0f;
56 static struct dtx_font *uifont;
57 static utk_widget *uiroot, *uiwin_new;
58 static utk_widget *uigrab;
59 static utk_widget *cbox_newsz;
61 static struct level lvl;
63 static const char *opt_fname;
66 int main(int argc, char **argv)
68 glutInit(&argc, argv);
70 if(parse_args(argc, argv) == -1) {
74 glutInitWindowSize(1280, 800);
75 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE);
76 glutCreateWindow("dunger");
78 win_width = glutGet(GLUT_WINDOW_WIDTH);
79 win_height = glutGet(GLUT_WINDOW_HEIGHT);
81 glutDisplayFunc(display);
82 glutReshapeFunc(reshape);
83 glutKeyboardFunc(keyb);
84 glutKeyboardUpFunc(keyup);
86 glutMotionFunc(motion);
87 glutPassiveMotionFunc(motion);
102 utk_widget *win, *hbox, *vbox;
104 glEnable(GL_MULTISAMPLE);
106 glClearColor(0.15, 0.15, 0.15, 1);
108 if(!(uifont = dtx_open_font("uifont.ttf", 0))) {
109 fprintf(stderr, "failed to open uifont.ttf\n");
112 dtx_prepare_range(uifont, FONTSZ, ' ', 'z');
113 dtx_use_font(uifont, FONTSZ);
115 if(!(uiroot = utk_init(win_width / uiscale, win_height / uiscale))) {
116 fprintf(stderr, "failed to initialized ubertk\n");
119 utk_set_color_func(ucolor);
120 utk_set_clip_func(uclip);
121 utk_set_image_func(uimage);
122 utk_set_rect_func(urect);
123 utk_set_line_func(uline);
124 utk_set_text_func(utext);
125 utk_set_text_spacing_func(utextspacing);
126 utk_set_text_width_func(utextwidth);
128 win = utk_vbox(uiroot, 0, UTK_DEF_SPACING);
129 utk_set_pos(win, 15, 15);
130 utk_button(win, "New", 0, 0, cb_new, 0);
131 utk_button(win, "Open ...", 0, 0, cb_open, 0);
132 utk_button(win, "Save ...", 0, 0, cb_save, 0);
133 utk_label(win, "-- Tools --");
134 utk_radiobox(win, "Draw", 1, cb_toolselect, (void*)TOOL_DRAW);
135 utk_radiobox(win, "Player start", 0, cb_toolselect, (void*)TOOL_PSTART);
137 uiwin_new = utk_window(uiroot, (win_width - 220) / 2, (win_height - 150) / 2,
138 220, 150, "New level");
139 vbox = utk_vbox(uiwin_new, UTK_DEF_PADDING, UTK_DEF_SPACING);
141 const char *items[] = {"small (16x16)", "medium (24x24)", "large (32x32)"};
142 cbox_newsz = utk_combobox_items(vbox, items, sizeof items / sizeof *items, 0, 0);
143 utk_select(cbox_newsz, 2);
145 hbox = utk_hbox(vbox, UTK_DEF_PADDING, UTK_DEF_SPACING);
146 utk_button(hbox, "OK", 0, 0, cb_new_ok, 0);
147 utk_button(hbox, "Cancel", 0, 0, cb_cancel, uiwin_new);
148 pad = utk_get_padding(uiwin_new);
149 utk_set_size(uiwin_new, utk_get_width(vbox) + pad * 2.0f, utk_get_height(vbox) + pad * 2.0f);
153 if(load_level(&lvl, opt_fname) == -1) {
154 fprintf(stderr, "failed to load level: %s\n", opt_fname);
158 if(init_level(&lvl, 32, 32) == -1) {
159 fprintf(stderr, "failed to create level\n");
163 if(init_lview(&lvl) == -1) {
167 splitx = UISPLIT * uiscale;
168 view_width = win_width - splitx;
169 view_height = win_height;
174 static void cleanup(void)
178 dtx_close_font(uifont);
182 static void display(void)
184 glClear(GL_COLOR_BUFFER_BIT);
186 glMatrixMode(GL_MODELVIEW);
191 glMatrixMode(GL_PROJECTION);
193 glOrtho(0, view_width, 0, view_height, -1, 1);
194 glViewport(splitx, 0, view_width, view_height);
197 glColor3f(0.1, 0.1, 0.1);
199 glVertex2f(view_width, 0);
200 glVertex2f(view_width, view_height);
201 glVertex2f(0, view_height);
208 glMatrixMode(GL_PROJECTION);
210 glOrtho(0, win_width, win_height, 0, -1, 1);
211 glViewport(0, 0, win_width, win_height);
214 glColor3f(0.25, 0.25, 0.25);
216 glVertex2f(splitx, 0);
217 glVertex2f(splitx, win_height);
218 glVertex2f(0, win_height);
222 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
230 static void reshape(int x, int y)
236 utk_set_size(uiroot, x / uiscale, y / uiscale);
239 lview_viewport(splitx, 0, x - splitx, y);
242 static void keyb(unsigned char key, int x, int y)
247 if(utk_is_dialog(uigrab)) {
248 utk_destroy_window(uigrab);
262 utk_keyboard_event(key, 1);
266 static void keyup(unsigned char key, int x, int y)
268 utk_keyboard_event(key, 0);
272 static void mouse(int bn, int st, int x, int y)
274 int bidx = bn - GLUT_LEFT_BUTTON;
275 int press = st == GLUT_DOWN;
277 bnstate[bidx] = press;
286 clickx = clicky = -1;
289 if(press) zoom_lview(0.1);
291 if(press) zoom_lview(-0.1);
295 lview_mbutton(bidx, press, x, y);
298 utk_mbutton_event(bidx, press, x / uiscale, y / uiscale);
302 static void motion(int x, int y)
310 if(clickx >= splitx) {
320 utk_mmotion_event(x / uiscale, y / uiscale);
324 static void cb_new(utk_event *ev, void *data)
330 static void cb_new_ok(utk_event *ev, void *data)
332 static int levsz[] = {16, 24, 32};
336 sz = levsz[utk_get_selected(cbox_newsz)];
338 if(init_level(&newlvl, sz, sz) == -1) {
339 utk_message_dialog("failed to create new level", UTK_MSG_TYPE_ERROR,
340 UTK_MSG_BN_OK, cb_cancel, 0);
354 static void cb_open(utk_event *ev, void *data)
356 uigrab = utk_file_dialog(UTK_FILE_DIALOG_OPEN, 0, "Level file (*.lvl) [.lvl]", 0, cb_open_ok, 0);
359 static void cb_open_ok(utk_event *ev, void *data)
364 utk_widget *dlg = utk_event_widget(ev);
365 path = utk_file_dialog_path(dlg);
366 printf("selected: %s\n", path);
367 if(load_level(&lvl, path) == -1) {
368 errmsg = alloca(strlen(path) + 32);
369 sprintf(errmsg, "Failed to load level: %s", path);
371 utk_destroy_window(dlg);
372 if(uigrab == dlg) uigrab = 0;
375 uigrab = utk_message_dialog(errmsg, UTK_MSG_TYPE_ERROR, UTK_MSG_BN_OK, cb_cancel, 0);
379 static void cb_save(utk_event *ev, void *data)
381 uigrab = utk_file_dialog(UTK_FILE_DIALOG_SAVE, 0, "Level file (*.lvl) [.lvl]", 0, cb_save_ok, 0);
384 static void cb_save_ok(utk_event *ev, void *data)
389 utk_widget *dlg = utk_event_widget(ev);
390 path = utk_file_dialog_path(dlg);
391 printf("selected: %s\n", path);
392 if(save_level(&lvl, path) == -1) {
393 errmsg = alloca(strlen(path) + 32);
394 sprintf(errmsg, "Failed to save level file: %s", path);
396 utk_destroy_window(dlg);
397 if(uigrab == dlg) uigrab = 0;
400 uigrab = utk_message_dialog(errmsg, UTK_MSG_TYPE_ERROR, UTK_MSG_BN_OK, cb_cancel, 0);
404 static void cb_cancel(utk_event *ev, void *data)
406 if(!data) data = utk_get_window(utk_event_widget(ev));
408 if(utk_is_dialog(data)) {
409 utk_destroy_window(data);
416 static void cb_toolselect(utk_event *ev, void *data)
418 utk_widget *w = utk_event_widget(ev);
419 if(utk_is_checked(w)) {
420 tool = (intptr_t)data;
424 static int parse_args(int argc, char **argv)
428 for(i=1; i<argc; i++) {
429 if(argv[i][0] == '-') {
430 if(strcmp(argv[i], "-uiscale") == 0) {
431 if(!argv[++i] || !(uiscale = atoi(argv[i]))) {
432 fprintf(stderr, "-uiscale should be followed by a positive number\n");
435 } else if(strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "-h") == 0) {
436 printf("Usage: %s [options]\n", argv[0]);
437 printf("Options:\n");
438 printf(" -uiscale <scale>: UI scale factor (default: 1)\n");
439 printf(" -h,-help: print usage and exit\n");
442 fprintf(stderr, "unknown option: %s\n", argv[i]);
447 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
456 /* --- ubertk callbacks --- */
458 static void ucolor(int r, int g, int b, int a)
460 glColor4ub(r, g, b, a);
463 static void uclip(int x1, int y1, int x2, int y2)
465 if(!(x1 | y1 | x2 | y2)) {
466 glDisable(GL_SCISSOR_TEST);
468 glEnable(GL_SCISSOR_TEST);
476 glScissor(x1, win_height - y2, x2 - x1, y2 - y1);
479 static void uimage(int x, int y, const void *pix, int xsz, int ysz)
482 glRasterPos2f(x * uiscale, y * uiscale);
483 glDrawPixels(xsz, ysz, GL_BGRA, GL_UNSIGNED_BYTE, pix);
486 static void urect(int x1, int y1, int x2, int y2)
488 glRectf(x1 * uiscale, y1 * uiscale, x2 * uiscale, y2 * uiscale);
491 static void uline(int x1, int y1, int x2, int y2, int width)
495 glVertex2f(x1 * uiscale, y1 * uiscale);
496 glVertex2f(x2 * uiscale, y2 * uiscale);
500 static void utext(int x, int y, const char *txt, int sz)
502 glMatrixMode(GL_PROJECTION);
504 glTranslatef(x * uiscale, (y - dtx_baseline()) * uiscale, 0);
505 glScalef(uiscale, -uiscale, 1);
513 static int utextspacing(void)
515 return dtx_line_height();
518 static int utextwidth(const char *txt, int sz)
520 return dtx_string_width(txt);