settings menu & texsheet
[vg.git] / vg_settings_menu.h
1 #ifndef VG_SETTINGS_MENU_H
2 #define VG_SETTINGS_MENU_H
3
4 #include "vg.h"
5 #include "vg_imgui.h"
6
7 struct ui_enum_opt vg_settings_vsync_enum[] = {
8 { 0, "None" },
9 { 1, "On" },
10 {-1, "Adaptive" },
11 };
12
13 struct ui_enum_opt vg_settings_quality_enum[] = {
14 { 0, "High Quality" },
15 { 1, "Faster" },
16 { 2, "Absolute Minimum" },
17 };
18
19 struct ui_enum_opt vg_settings_screen_mode_enum[] = {
20 { 0, "Fullscreen (desktop)" },
21 { 1, "Fullscreen (native)" },
22 { 2, "Floating Window" }
23 };
24
25 struct {
26 struct vg_setting_ranged_i32{
27 i32 new_value, *actual_value, min, max;
28 char buf[10];
29 const char *label;
30 }
31 fps_limit;
32
33 struct vg_setting_enum{
34 i32 new_value, *actual_value;
35
36 struct ui_enum_opt *options;
37 u32 option_count;
38 const char *label;
39 }
40 vsync, quality, screenmode;
41
42 int windowed_before[4];
43 }
44 static vg_settings = {
45 .fps_limit = { .label = "Fps Limit",
46 .min=24, .max=300, .actual_value = &vg.fps_limit },
47 .vsync = { .label = "Vsync",
48 .actual_value = &vg.vsync,
49 .options = vg_settings_vsync_enum, .option_count = 3 },
50 .quality = { .label = "Graphic Quality",
51 .actual_value = &vg.quality_profile,
52 .options = vg_settings_quality_enum, .option_count = 3 },
53 .screenmode = { .label = "Type",
54 .actual_value = &vg.screen_mode,
55 .options = vg_settings_screen_mode_enum, .option_count=3 }
56
57 };
58
59 static void vg_settings_ui_draw_diff( ui_rect orig ){
60 ui_rect l,r;
61 ui_split( orig, k_ui_axis_v, -32, 0, l, r );
62 ui_text( r, "*", 1, k_ui_align_middle_center, ui_colour(k_ui_blue) );
63 }
64
65 /* i32 settings
66 * ------------------------------------------------------------------------- */
67
68 static void vg_settings_ui_int( char *buf, u32 len ){
69 for( u32 i=0, j=0; i<len; i ++ ){
70 if( ((buf[i] >= '0') && (buf[i] <= '9')) || (buf[i] == '\0') )
71 buf[j ++] = buf[i];
72 }
73 }
74
75 struct ui_textbox_callbacks static vg_settings_ui_int_callbacks = {
76 .change = vg_settings_ui_int
77 };
78
79 static bool vg_settings_ranged_i32_valid( struct vg_setting_ranged_i32 *prop ){
80 if( prop->new_value < prop->min ) return 0;
81 if( prop->new_value > prop->max ) return 0;
82 return 1;
83 }
84
85 static bool vg_settings_ranged_i32_diff( struct vg_setting_ranged_i32 *prop ){
86 if( prop->new_value != *prop->actual_value ) return 1;
87 else return 0;
88 }
89
90 static bool vg_settings_ui_ranged_i32( struct vg_setting_ranged_i32 *prop,
91 ui_rect rect ){
92 ui_rect orig;
93 rect_copy( rect, orig );
94
95 ui_textbox( rect, prop->label, prop->buf, sizeof(prop->buf),
96 1, 0, &vg_settings_ui_int_callbacks );
97 prop->new_value = atoi( prop->buf );
98
99 if( vg_settings_ranged_i32_diff( prop ) )
100 vg_settings_ui_draw_diff( orig );
101
102 bool valid = vg_settings_ranged_i32_valid( prop );
103 if( !valid ){
104 ui_rect _null, line;
105 ui_split( orig, k_ui_axis_h, -1, 0, _null, line );
106 line[1] += 3;
107
108 ui_fill( line, ui_colour( k_ui_red ) );
109 }
110
111 return valid;
112 }
113
114 static void ui_settings_ranged_i32_init( struct vg_setting_ranged_i32 *prop ){
115 vg_str tmp;
116 vg_strnull( &tmp, prop->buf, sizeof(prop->buf) );
117 vg_strcati32( &tmp, *prop->actual_value );
118 prop->new_value = *prop->actual_value;
119 }
120
121 /* enum settings
122 * ------------------------------------------------------------------------- */
123
124 static bool vg_settings_enum_diff( struct vg_setting_enum *prop ){
125 if( prop->new_value != *prop->actual_value ) return 1;
126 else return 0;
127 }
128
129 static bool vg_settings_enum( struct vg_setting_enum *prop, ui_rect rect ){
130 ui_rect orig;
131 rect_copy( rect, orig );
132
133 ui_enum( rect, prop->label,
134 prop->options, prop->option_count, &prop->new_value );
135
136 if( vg_settings_enum_diff( prop ) )
137 vg_settings_ui_draw_diff( orig );
138
139 return 1;
140 }
141
142 static void ui_settings_enum_init( struct vg_setting_enum *prop ){
143 prop->new_value = *prop->actual_value;
144 }
145
146 /* .. */
147
148 static void vg_settings_ui_header( ui_rect inout_panel, const char *name ){
149 ui_rect rect;
150 ui_standard_widget( inout_panel, rect, 2 );
151 ui_text( rect, name, 1, k_ui_align_middle_center, ui_colour(k_ui_fg+3) );
152 }
153
154 static void vg_settings_video_apply(void){
155 if( vg_settings_enum_diff( &vg_settings.screenmode ) ){
156 vg.screen_mode = vg_settings.screenmode.new_value;
157
158 if( (vg.screen_mode == 0) || (vg.screen_mode == 1) ){
159 SDL_GetWindowPosition( vg.window,
160 &vg_settings.windowed_before[0],
161 &vg_settings.windowed_before[1] );
162 vg_settings.windowed_before[2] = vg.window_x;
163 vg_settings.windowed_before[3] = vg.window_y;
164
165 SDL_DisplayMode video_mode;
166 if( SDL_GetDesktopDisplayMode( 0, &video_mode ) ){
167 vg_error("SDL_GetDesktopDisplayMode failed: %s\n", SDL_GetError());
168 }
169 else {
170 //vg.display_refresh_rate = video_mode.refresh_rate;
171 vg.window_x = video_mode.w;
172 vg.window_y = video_mode.h;
173 }
174 SDL_SetWindowResizable( vg.window, SDL_FALSE );
175 SDL_SetWindowSize( vg.window, vg.window_x, vg.window_y );
176 }
177
178 if( vg.screen_mode == 0 )
179 SDL_SetWindowFullscreen( vg.window, SDL_WINDOW_FULLSCREEN_DESKTOP );
180 if( vg.screen_mode == 1 )
181 SDL_SetWindowFullscreen( vg.window, SDL_WINDOW_FULLSCREEN );
182 if( vg.screen_mode == 2 ){
183 SDL_SetWindowFullscreen( vg.window, 0 );
184 SDL_SetWindowSize( vg.window,
185 vg_settings.windowed_before[2],
186 vg_settings.windowed_before[3] );
187 SDL_SetWindowPosition( vg.window,
188 vg_settings.windowed_before[0],
189 vg_settings.windowed_before[1] );
190 SDL_SetWindowResizable( vg.window, SDL_TRUE );
191 }
192 }
193
194 vg.fps_limit = vg_settings.fps_limit.new_value;
195 vg.quality_profile = vg_settings.quality.new_value;
196 vg.vsync = vg_settings.vsync.new_value;
197 }
198
199 static void aaaaaaaaaaaaaaaaa( ui_rect r );
200 static void vg_settings_video_gui( ui_rect panel ){
201 bool validated = 1;
202 ui_rect rq;
203 ui_standard_widget( panel, rq, 1 );
204 vg_settings_enum( &vg_settings.quality, rq );
205
206 /* FIXME */
207 #if 0
208 if( vg.vsync_feature == k_vsync_feature_error ){
209 ui_info( panel, "There was an error activating vsync feature." );
210 }
211 #endif
212
213 /* frame timing */
214 vg_settings_ui_header( panel, "Frame Timing" );
215 ui_rect duo, d0,d1;
216 ui_standard_widget( panel, duo, 1 );
217 ui_split_ratio( duo, k_ui_axis_v, 0.5f, 16, d0, d1 );
218
219 vg_settings_enum( &vg_settings.vsync, d0 );
220 validated &= vg_settings_ui_ranged_i32( &vg_settings.fps_limit, d1 );
221
222 ui_standard_widget( panel, duo, 10 );
223 aaaaaaaaaaaaaaaaa( duo );
224
225 /* window spec */
226 vg_settings_ui_header( panel, "Window Specification" );
227
228 ui_standard_widget( panel, duo, 1 );
229 vg_settings_enum( &vg_settings.screenmode, duo );
230
231 /* apply */
232 ui_rect last_row;
233 ui_px height = (vg_ui.font->glyph_height + 18) * k_ui_scale;
234 ui_split( panel, k_ui_axis_h, -height, k_ui_padding,
235 panel, last_row );
236
237 const char *string = "Apply";
238 if( validated ){
239 if( ui_button( last_row, string ) == 1 )
240 vg_settings_video_apply();
241 }
242 else{
243 ui_rect rect;
244 ui_standard_widget( last_row, rect, 1 );
245 ui_fill( rect, ui_colour( k_ui_bg+1 ) );
246 ui_outline( rect, -1, ui_colour( k_ui_red ), 0 );
247
248 ui_rect t = { 0,0, ui_text_line_width( string ), 14 };
249 ui_rect_center( rect, t );
250 ui_text( t, string, 1, k_ui_align_left, ui_colour(k_ui_fg+3) );
251 }
252 }
253
254 static void vg_settings_gui(void){
255 ui_rect null;
256 ui_rect screen = { 0, 0, vg.window_x, vg.window_y };
257 ui_rect window = { 0, 0, 1000, 700 };
258 ui_rect_center( screen, window );
259 vg_ui.wants_mouse = 1;
260
261 ui_fill( window, ui_colour( k_ui_bg+1 ) );
262 ui_outline( window, 1, ui_colour( k_ui_bg+7 ), 0 );
263
264 ui_rect title, panel;
265 ui_split( window, k_ui_axis_h, 28, 0, title, panel );
266 ui_fill( title, ui_colour( k_ui_bg+7 ) );
267 ui_text( title, "Settings", 1, k_ui_align_middle_center,
268 ui_colourcont(k_ui_bg+7) );
269
270 ui_rect quit_button;
271 ui_split( title, k_ui_axis_v, title[2]-title[3], 2, title, quit_button );
272
273 if( ui_button_text( quit_button, "X", 1 ) == 1 ){
274 vg.settings_open = 0;
275 return;
276 }
277
278 ui_rect_pad( panel, (ui_px[2]){ 8, 8 } );
279
280 static i32 page = 0;
281 ui_tabs( panel, panel, (const char *[]){ "video", "audio", "game" },
282 3, &page );
283
284 if( page == 0 ){
285 vg_settings_video_gui( panel );
286 }
287 }
288
289 static int cmd_vg_settings_toggle( int argc, const char *argv[] ){
290 vg.settings_open = !vg.settings_open;
291
292 if( vg.settings_open ){
293 ui_settings_ranged_i32_init( &vg_settings.fps_limit );
294 ui_settings_enum_init( &vg_settings.vsync );
295 ui_settings_enum_init( &vg_settings.quality );
296 ui_settings_enum_init( &vg_settings.screenmode );
297 }
298 return 0;
299 }
300
301 #endif /* VG_SETTINGS_MENU_H */