added minimum turn option, to discretize turns in VR
[laserbrain_demo] / src / opt.cc
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <optcfg.h>
5 #include "opt.h"
6
7 Options opt;
8
9 Options def_opt = {
10         1280, 800,
11         false,  // vr
12         false,  // fullscreen
13         0,              // scene file
14         true,   // music
15         true,   // reflections
16         0,              // data url
17         0.0f    // minimum turn angle
18 };
19
20 enum {
21         OPT_SIZE,
22         OPT_VR,
23         OPT_FULLSCREEN,
24         OPT_WINDOWED,
25         OPT_SCENEFILE,
26         OPT_MUSIC,
27         OPT_REFLECT,
28         OPT_DATAURL,
29         OPT_MIN_TURN,
30         OPT_HELP
31 };
32
33 static optcfg_option options[] = {
34         // short, long, id, desc
35         {'s', "size", OPT_SIZE, "window size (WxH)"},
36         {0, "vr", OPT_VR, "enable VR mode"},
37         {'f', "fullscreen", OPT_FULLSCREEN, "run in fullscreen mode"},
38         {'w', "windowed", OPT_WINDOWED, "run in windowed mode"},
39         {0, "scene", OPT_SCENEFILE, "scene file to open"},
40         {'m', "music", OPT_MUSIC, "play background audio"},
41         {'r', "reflect", OPT_REFLECT, "render reflections"},
42         {0, "url", OPT_DATAURL, "data URL"},
43         {0, "minturn", OPT_MIN_TURN, "minimum turn angle"},
44         {'h', "help", OPT_HELP, "print usage and exit"},
45         OPTCFG_OPTIONS_END
46 };
47
48 static int opt_handler(optcfg *oc, int opt, void *cls);
49 static int arg_handler(optcfg *oc, const char *arg, void *cls);
50
51 bool init_options(int argc, char **argv, const char *cfgfile)
52 {
53         // default options
54         opt = def_opt;
55
56         optcfg *oc = optcfg_init(options);
57         optcfg_set_opt_callback(oc, opt_handler, 0);
58         optcfg_set_arg_callback(oc, arg_handler, 0);
59
60         if(cfgfile) {
61                 optcfg_parse_config_file(oc, cfgfile);
62         }
63
64         if(argv && optcfg_parse_args(oc, argc, argv) == -1) {
65                 fprintf(stderr, "invalid option\n");
66                 optcfg_destroy(oc);
67                 return false;
68         }
69
70         optcfg_destroy(oc);
71         return true;
72 }
73
74 static bool is_enabled(optcfg *oc)
75 {
76         int res;
77         optcfg_enabled_value(oc, &res);
78         return res != 0;
79 }
80
81 static int opt_handler(optcfg *oc, int optid, void *cls)
82 {
83         switch(optid) {
84         case OPT_SIZE:
85                 {
86                         char *valstr = optcfg_next_value(oc);
87                         if(!valstr || sscanf(valstr, "%dx%d", &opt.width, &opt.height) != 2) {
88                                 fprintf(stderr, "size must be in the form: WIDTHxHEIGHT\n");
89                                 return -1;
90                         }
91                 }
92                 break;
93
94         case OPT_VR:
95                 opt.vr = is_enabled(oc);
96                 break;
97
98         case OPT_FULLSCREEN:
99                 opt.fullscreen = is_enabled(oc);
100                 break;
101
102         case OPT_WINDOWED:
103                 opt.fullscreen = !is_enabled(oc);
104                 break;
105
106         case OPT_SCENEFILE:
107                 opt.scenefile = strdup(optcfg_next_value(oc));
108                 break;
109
110         case OPT_MUSIC:
111                 opt.music = is_enabled(oc);
112                 break;
113
114         case OPT_REFLECT:
115                 opt.reflect = is_enabled(oc);
116                 break;
117
118         case OPT_DATAURL:
119                 opt.data_url = strdup(optcfg_next_value(oc));
120                 break;
121
122         case OPT_MIN_TURN:
123                 {
124                         int deg;
125                         char *valstr = optcfg_next_value(oc);
126
127                         if(!valstr || sscanf(valstr, "%d", &deg) != 1) {
128                                 fprintf(stderr, "minimum turn must be a number >= 0 in degrees\n");
129                                 return -1;
130                         }
131                         opt.min_turn = deg;
132                 }
133                 break;
134
135         case OPT_HELP:
136                 printf("Usage: demo [options]\nOptions:\n");
137                 optcfg_print_options(oc);
138                 exit(0);
139         }
140         return 0;
141 }
142
143 static int arg_handler(optcfg *oc, const char *arg, void *cls)
144 {
145         if(opt.scenefile) {
146                 fprintf(stderr, "unexpected argument: %s\n", arg);
147                 return -1;
148         }
149         opt.scenefile = arg;
150         return 0;
151 }