moving along slowly
[retroray] / src / app.c
1 /*
2 RetroRay - integrated standalone vintage modeller/renderer
3 Copyright (C) 2023  John Tsiombikas <nuclear@mutantstargoat.com>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18 #include "config.h"
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <time.h>
24 #include "gaw/gaw.h"
25 #include "app.h"
26 #include "options.h"
27 #include "font.h"
28 #include "util.h"
29
30 static void txdraw(struct dtx_vertex *v, int vcount, struct dtx_pixmap *pixmap, void *cls);
31
32 int mouse_x, mouse_y, mouse_state[3];
33 unsigned int modkeys;
34 int win_width, win_height;
35 float win_aspect;
36 int fullscr;
37
38 long time_msec;
39
40 struct app_screen *cur_scr;
41
42 struct font *uifont;
43
44 /* available screens */
45 #define MAX_SCREENS     8
46 static struct app_screen *screens[MAX_SCREENS];
47 static int num_screens;
48
49
50 int app_init(void)
51 {
52         int i;
53         char *start_scr_name;
54
55 #if !defined(NDEBUG) && defined(DBG_FPEXCEPT)
56         printf("floating point exceptions enabled\n");
57         enable_fpexcept();
58 #endif
59
60         load_options("retroray.cfg");
61         app_resize(opt.xres, opt.yres);
62         app_vsync(opt.vsync);
63         if(opt.fullscreen) {
64                 app_fullscreen(1);
65         }
66
67         dtx_target_user(txdraw, 0);
68
69         uifont = malloc_nf(sizeof *uifont);
70         if(load_font(uifont, "data/uifont.gmp") == -1) {
71                 free(uifont);
72                 return -1;
73         }
74
75         /* initialize screens */
76         screens[num_screens++] = &scr_model;
77         screens[num_screens++] = &scr_rend;
78
79         start_scr_name = getenv("START_SCREEN");
80
81         for(i=0; i<num_screens; i++) {
82                 if(screens[i]->init() == -1) {
83                         return -1;
84                 }
85         }
86
87         time_msec = app_getmsec();
88
89         for(i=0; i<num_screens; i++) {
90                 if(screens[i]->name && start_scr_name && strcmp(screens[i]->name, start_scr_name) == 0) {
91                         app_chscr(screens[i]);
92                         break;
93                 }
94         }
95         if(!cur_scr) {
96                 app_chscr(&scr_model);
97         }
98
99         return 0;
100 }
101
102 void app_shutdown(void)
103 {
104         int i;
105
106         putchar('\n');
107
108         save_options("retroray.cfg");
109
110         for(i=0; i<num_screens; i++) {
111                 if(screens[i]->destroy) {
112                         screens[i]->destroy();
113                 }
114         }
115
116         destroy_font(uifont);
117         free(uifont);
118 }
119
120 void app_display(void)
121 {
122         time_msec = app_getmsec();
123
124         cur_scr->display();
125
126         app_swap_buffers();
127 }
128
129 void app_reshape(int x, int y)
130 {
131         win_width = x;
132         win_height = y;
133         win_aspect = (float)x / (float)y;
134         gaw_viewport(0, 0, x, y);
135
136         if(cur_scr && cur_scr->reshape) {
137                 cur_scr->reshape(x, y);
138         }
139 }
140
141 void app_keyboard(int key, int press)
142 {
143         if(press) {
144                 switch(key) {
145 #ifdef DBG_ESCQUIT
146                 case 27:
147                         app_quit();
148                         return;
149 #endif
150
151                 case '\n':
152                 case '\r':
153                         if(modkeys & KEY_MOD_ALT) {
154                 case KEY_F11:
155                                 app_fullscreen(-1);
156                                 return;
157                         }
158                         break;
159                 }
160         }
161
162         if(cur_scr && cur_scr->keyboard) {
163                 cur_scr->keyboard(key, press);
164         }
165 }
166
167 void app_mouse(int bn, int st, int x, int y)
168 {
169         mouse_x = x;
170         mouse_y = y;
171         if(bn < 3) {
172                 mouse_state[bn] = st;
173         }
174
175         if(cur_scr && cur_scr->mouse) {
176                 cur_scr->mouse(bn, st, x, y);
177         }
178 }
179
180 void app_motion(int x, int y)
181 {
182         if(cur_scr && cur_scr->motion) {
183                 cur_scr->motion(x, y);
184         }
185         mouse_x = x;
186         mouse_y = y;
187 }
188
189 void app_sball_motion(int x, int y, int z)
190 {
191         if(cur_scr->sball_motion) {
192                 cur_scr->sball_motion(x, y, z);
193         }
194 }
195
196 void app_sball_rotate(int x, int y, int z)
197 {
198         if(cur_scr->sball_rotate) {
199                 cur_scr->sball_rotate(x, y, z);
200         }
201 }
202
203 void app_sball_button(int bn, int st)
204 {
205         if(cur_scr->sball_button) {
206                 cur_scr->sball_button(bn, st);
207         }
208 }
209
210 void app_chscr(struct app_screen *scr)
211 {
212         struct app_screen *prev = cur_scr;
213
214         if(!scr) return;
215
216         if(scr->start && scr->start() == -1) {
217                 return;
218         }
219         if(scr->reshape) {
220                 scr->reshape(win_width, win_height);
221         }
222
223         if(prev && prev->stop) {
224                 prev->stop();
225         }
226         cur_scr = scr;
227 }
228
229 static void txdraw(struct dtx_vertex *v, int vcount, struct dtx_pixmap *pixmap, void *cls)
230 {
231         /*
232         int i, aref, npix;
233         unsigned char *src, *dest;
234         struct texture *tex = pixmap->udata;
235
236         if(!tex) {
237                 struct img_pixmap *img = img_create();
238                 img_set_pixels(img, pixmap->width, pixmap->height, IMG_FMT_RGBA32, 0);
239
240                 npix = pixmap->width * pixmap->height;
241                 src = pixmap->pixels;
242                 dest = img->pixels;
243                 for(i=0; i<npix; i++) {
244                         dest[0] = dest[1] = dest[2] = 0xff;
245                         dest[3] = *src++;
246                         dest += 4;
247                 }
248
249                 if(!(tex = tex_image(img))) {
250                         return;
251                 }
252                 pixmap->udata = tex;
253         }
254
255         gaw_save();
256         if(dtx_get(DTX_GL_BLEND)) {
257                 gaw_enable(GAW_BLEND);
258                 gaw_blend_func(GAW_SRC_ALPHA, GAW_ONE_MINUS_SRC_ALPHA);
259         } else {
260                 gaw_disable(GAW_BLEND);
261         }
262         if((aref = dtx_get(DTX_GL_ALPHATEST))) {
263                 gaw_enable(GAW_ALPHA_TEST);
264                 gaw_alpha_func(GAW_GREATER, aref);
265         } else {
266                 gaw_disable(GAW_ALPHA_TEST);
267         }
268
269         gaw_set_tex2d(tex->texid);
270
271         gaw_begin(GAW_TRIANGLES);
272         for(i=0; i<vcount; i++) {
273                 gaw_texcoord2f(v->s, v->t);
274                 gaw_vertex2f(v->x, v->y);
275                 v++;
276         }
277         gaw_end();
278
279         gaw_restore();
280         gaw_set_tex2d(0);
281         */
282 }