Add some challenges to the world map
[carveJwlIkooP6JGAAIwe30JlM.git] / menu.c
1 #pragma once
2 #include "skaterift.h"
3 #include "menu.h"
4 #include "model.h"
5 #include "entity.h"
6 #include "input.h"
7 #include "world_map.h"
8 #include "ent_miniworld.h"
9 #include "audio.h"
10 #include "workshop.h"
11 #include "gui.h"
12 #include "control_overlay.h"
13 #include "network.h"
14 #include "shaders/model_menu.h"
15
16 struct global_menu menu = { .skip_starter = 0 };
17
18 void menu_at_begin(void)
19 {
20 if( menu.skip_starter ) return;
21
22 skaterift.activity = k_skaterift_menu;
23 menu.page = k_menu_page_starter;
24 }
25
26 void menu_init(void)
27 {
28 vg_console_reg_var( "skip_starter_menu", &menu.skip_starter,
29 k_var_dtype_i32, VG_VAR_PERSISTENT );
30 }
31
32 void menu_open( enum menu_page page )
33 {
34 skaterift.activity = k_skaterift_menu;
35
36 if( page != k_menu_page_any )
37 {
38 menu.page = page;
39 }
40 }
41
42 bool menu_viewing_map(void)
43 {
44 return (skaterift.activity == k_skaterift_menu) &&
45 (menu.page == k_menu_page_main) &&
46 (menu.main_index == k_menu_main_map);
47 }
48
49 static void menu_decor_select( ui_rect rect )
50 {
51 ui_px b = vg_ui.font->sx, hb = b/2;
52 ui_rect a0 = { rect[0] - 20 - hb, rect[1] + rect[3]/2 - hb, b,b },
53 a1 = { rect[0] + rect[2] + 20 + hb, rect[1] + rect[3]/2 - hb, b,b };
54
55 ui_text( a0, "\x95", 1, k_ui_align_middle_center, 0 );
56 ui_text( a1, "\x93", 1, k_ui_align_middle_center, 0 );
57 }
58
59 static void menu_standard_widget( ui_rect inout_panel, ui_rect rect, ui_px s )
60 {
61 ui_split( inout_panel, k_ui_axis_h, vg_ui.font->sy*s*2,
62 8, rect, inout_panel );
63 }
64
65 static bool menu_slider( ui_rect inout_panel, bool select, const char *label,
66 const f32 disp_min, const f32 disp_max, f32 *value,
67 const char *format )
68 {
69 ui_rect rect, box;
70 menu_standard_widget( inout_panel, rect, 1 );
71 ui_label( rect, label, 1, 8, box );
72
73 f32 t;
74 enum ui_button_state state = ui_slider_base( box, 0, 1, value, &t ),
75 mask_using =
76 k_ui_button_holding_inside |
77 k_ui_button_holding_outside |
78 k_ui_button_click,
79 mask_brighter = mask_using | k_ui_button_hover;
80
81 if( vg_input.display_input_method == k_input_method_controller )
82 {
83 if( select )
84 {
85 f32 m = axis_state( k_sraxis_mbrowse_h );
86 if( fabsf(m) > 0.5f )
87 {
88 *value += m * vg.time_frame_delta * (1.0f/2.0f);
89 *value = vg_clampf( *value, 0, 1 );
90 }
91
92 menu_decor_select( rect );
93 state |= k_ui_button_hover;
94 }
95 }
96
97 ui_rect line = { box[0], box[1], t * (f32)box[2], box[3] };
98 ui_fill( line, state&mask_brighter? GUI_COL_ACTIVE: GUI_COL_NORM );
99 ui_fill( (ui_rect){ box[0]+line[2], box[1], box[2]-line[2], box[3] },
100 GUI_COL_DARK );
101
102 ui_outline( box, 1, state? GUI_COL_HI: GUI_COL_ACTIVE, 0 );
103 ui_slider_text( box, format, disp_min + (*value)*( disp_max-disp_min ) );
104
105 return (state & mask_using) && 1;
106 }
107
108 static bool menu_button( ui_rect inout_panel, bool select, const char *text )
109 {
110 ui_rect rect;
111 menu_standard_widget( inout_panel, rect, 1 );
112
113 enum ui_button_state state = k_ui_button_none;
114
115 if( vg_input.display_input_method == k_input_method_controller )
116 {
117 if( select )
118 {
119 menu_decor_select( rect );
120
121 if( button_down( k_srbind_maccept ) )
122 state = k_ui_button_click;
123 }
124 }
125 else
126 {
127 state = ui_button_base( rect );
128 select = 0;
129 }
130
131 if( state == k_ui_button_click )
132 {
133 ui_fill( rect, GUI_COL_DARK );
134 }
135 else if( state == k_ui_button_holding_inside )
136 {
137 ui_fill( rect, GUI_COL_DARK );
138 }
139 else if( state == k_ui_button_holding_outside )
140 {
141 ui_fill( rect, GUI_COL_DARK );
142 ui_outline( rect, 1, GUI_COL_CLICK, 0 );
143 }
144 else if( state == k_ui_button_hover )
145 {
146 ui_fill( rect, GUI_COL_ACTIVE );
147 ui_outline( rect, 1, GUI_COL_CLICK, 0 );
148 }
149 else
150 {
151 ui_fill( rect, select? GUI_COL_ACTIVE: GUI_COL_NORM );
152 if( select )
153 ui_outline(rect, 1, GUI_COL_HI, 0 );
154 }
155
156 ui_text( rect, text, 1, k_ui_align_middle_center, 0 );
157 return state == k_ui_button_click;
158 }
159
160 static bool menu_checkbox( ui_rect inout_panel, bool select,
161 const char *str_label, i32 *data )
162 {
163 ui_rect rect, label, box;
164 menu_standard_widget( inout_panel, rect, 1 );
165
166 ui_split( rect, k_ui_axis_v, -rect[3], 0, label, box );
167 ui_text( label, str_label, k_ui_scale, k_ui_align_middle_left, 0 );
168
169 enum ui_button_state state = k_ui_button_none;
170
171 if( vg_input.display_input_method == k_input_method_controller )
172 {
173 if( select )
174 {
175 menu_decor_select( rect );
176
177 if( button_down( k_srbind_maccept ) )
178 {
179 *data = (*data) ^ 0x1;
180 state = k_ui_button_click;
181 }
182 }
183 }
184 else
185 {
186 state = ui_checkbox_base( box, data );
187 select = 0;
188 }
189
190 if( state == k_ui_button_holding_inside )
191 {
192 ui_fill( box, GUI_COL_ACTIVE );
193 ui_outline( box, 1, GUI_COL_CLICK, 0 );
194 }
195 else if( state == k_ui_button_holding_outside )
196 {
197 ui_fill( box, GUI_COL_DARK );
198 ui_outline( box, 1, GUI_COL_CLICK, 0 );
199 }
200 else if( state == k_ui_button_hover )
201 {
202 ui_fill( box, GUI_COL_ACTIVE );
203 ui_outline( box, 1, GUI_COL_HI, 0 );
204 }
205 else
206 {
207 ui_fill( box, select? GUI_COL_ACTIVE: GUI_COL_DARK );
208 ui_outline( box, 1, select? GUI_COL_HI: GUI_COL_NORM, 0 );
209 }
210
211 bool changed = (state == k_ui_button_click);
212
213 if( *data )
214 {
215 ui_rect_pad( box, (ui_px[2]){8,8} );
216 ui_fill( box, GUI_COL_HI );
217 }
218
219 return changed;
220 }
221
222 static void menu_heading( ui_rect inout_panel, const char *label, u32 colour )
223 {
224 ui_rect rect;
225 menu_standard_widget( inout_panel, rect, 1 );
226
227 rect[0] -= 8;
228 rect[2] += 16;
229
230 u32 c0 = ui_opacity( GUI_COL_DARK, 0.36f ),
231 c1 = ui_opacity( GUI_COL_DARK, 0.5f );
232
233 struct ui_vert *vs = ui_fill( rect, c0 );
234
235 vs[0].colour = c1;
236 vs[1].colour = c1;
237
238 rect[1] += 4;
239 ui_text( rect, label, 1, k_ui_align_middle_center, 1 );
240 rect[0] += 1;
241 rect[1] -= 1;
242 ui_text( rect, label, 1, k_ui_align_middle_center, colour? colour:
243 ui_colour(k_ui_blue+k_ui_brighter) );
244 }
245
246 static u32 medal_colour( u32 flags )
247 {
248 if( flags & k_ent_route_flag_achieve_gold )
249 return ui_colour( k_ui_yellow );
250 else if( flags & k_ent_route_flag_achieve_silver )
251 return ui_colour( k_ui_fg );
252 else return 0;
253 }
254
255 void menu_gui(void)
256 {
257 if( button_down( k_srbind_mopen ) )
258 {
259 if( skaterift.activity == k_skaterift_default )
260 {
261 menu_open( k_menu_page_main );
262 return;
263 }
264 }
265
266 if( skaterift.activity != k_skaterift_menu )
267 return;
268
269 /* get buttons inputs
270 * -------------------------------------------------------------------*/
271 int ml = button_down( k_srbind_mleft ),
272 mr = button_down( k_srbind_mright ),
273 mu = button_down( k_srbind_mup ),
274 md = button_down( k_srbind_mdown ),
275 mh = ml-mr,
276 mv = mu-md,
277 enter = button_down( k_srbind_maccept );
278
279 if( vg_input.display_input_method == k_input_method_kbm )
280 {
281 vg_ui.wants_mouse = 1;
282 }
283
284 if( skaterift.activity != k_skaterift_menu ) return;
285
286 if( vg.settings_open )
287 {
288 if( button_down( k_srbind_mback ) )
289 {
290 vg_settings_close();
291 srinput.state = k_input_state_resume;
292 }
293
294 return;
295 }
296
297 if( menu.page == k_menu_page_credits )
298 {
299 ui_rect panel = { 0,0, 600, 400 },
300 screen = { 0,0, vg.window_x,vg.window_y };
301 ui_rect_center( screen, panel );
302 ui_fill( panel, GUI_COL_DARK );
303 ui_outline( panel, 1, GUI_COL_NORM, 0 );
304 ui_rect_pad( panel, (ui_px[]){8,8} );
305
306 ui_rect title;
307 ui_split( panel, k_ui_axis_h, 28*2, 0, title, panel );
308 ui_font_face( &vgf_default_title );
309 ui_text( title, "Skate Rift - Credits", 1, k_ui_align_middle_center, 0 );
310
311 ui_split( panel, k_ui_axis_h, 28, 0, title, panel );
312 ui_font_face( &vgf_default_large );
313 ui_text( title, "Mt.Zero Software", 1, k_ui_align_middle_center, 0 );
314
315 ui_split( panel, k_ui_axis_h, 8, 0, title, panel );
316 ui_split( panel, k_ui_axis_h, 28*2, 0, title, panel );
317 ui_font_face( &vgf_default_title );
318 ui_text( title, "Free Software", 1, k_ui_align_middle_center, 0 );
319
320 ui_split( panel, k_ui_axis_h, 8, 0, title, panel );
321 ui_font_face( &vgf_default_large );
322 ui_text( panel,
323 "Sam Lantinga - SDL2 - libsdl.org\n"
324 "Hunter WB - Anyascii\n"
325 "David Herberth - GLAD\n"
326 "Dominic Szablewski - QOI - qoiformat.org\n"
327 "Sean Barrett - stb_image, stb_vorbis,\n"
328 " stb_include\n"
329 "Khronos Group - OpenGL\n"
330 , 1, k_ui_align_left, 0 );
331
332 ui_rect end = { panel[0], panel[1] + panel[3] - 64, panel[2], 64 };
333
334 if( menu_button( end, 1, "Back" ) || button_down( k_srbind_mback ) )
335 {
336 menu.page = k_menu_page_main;
337 }
338
339 goto menu_draw;
340 }
341
342 /* TOP BAR
343 * -------------------------------------------------------------------*/
344
345 ui_font_face( &vgf_default_title );
346 ui_px height = vg_ui.font->ch + 16;
347 ui_rect topbar = { 0, 0, vg.window_x, height };
348
349 const char *opts[] = {
350 [k_menu_main_main] = "Menu",
351 [k_menu_main_map] = "Map",
352 [k_menu_main_settings ] = "Settings",
353 [k_menu_main_guide ] = "Guides"
354 };
355
356 /* TAB CONTROL */
357 u8 lb_down = 0, rb_down = 0;
358 vg_exec_input_program( k_vg_input_type_button_u8,
359 (vg_input_op[]){
360 vg_joy_button, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, vg_end
361 }, &rb_down );
362 vg_exec_input_program( k_vg_input_type_button_u8,
363 (vg_input_op[]){
364 vg_joy_button, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, vg_end
365 }, &lb_down );
366
367 if( menu.repeater > 0.0f )
368 {
369 menu.repeater -= vg_minf( vg.time_frame_delta, 0.5f );
370 }
371 else
372 {
373 if( lb_down != rb_down )
374 {
375 menu.main_index += rb_down;
376 menu.main_index -= lb_down;
377 menu.repeater += 0.2f;
378
379 if( menu.main_index == -1 )
380 menu.main_index ++;
381
382 if( menu.main_index == vg_list_size(opts) )
383 menu.main_index --;
384 }
385 }
386
387 ui_px x = 0, spacer = 8;
388 for( u32 draw=0; draw<2; draw ++ )
389 {
390 if( vg_input.display_input_method == k_input_method_controller )
391 {
392 if( draw )
393 {
394 ui_rect inf_lb = { x, 0, 32, height };
395 ui_fill( inf_lb, lb_down? GUI_COL_NORM: GUI_COL_NORM );
396 ui_text( inf_lb, "\x91", 1, k_ui_align_middle_center, 0 );
397 }
398 x += 32 + spacer;
399 }
400
401 for( i32 i=0; i<vg_list_size(opts); i ++ )
402 {
403 ui_rect box = { x, 0, ui_text_line_width(opts[i]) + 32, height };
404
405 if( draw )
406 {
407 enum ui_button_state state = ui_button_base( box );
408 if( state == k_ui_button_click )
409 {
410 ui_fill( box, GUI_COL_DARK );
411 menu.main_index = i;
412 }
413 else if( state == k_ui_button_holding_inside )
414 {
415 ui_fill( box, GUI_COL_DARK );
416 }
417 else if( state == k_ui_button_holding_outside )
418 {
419 ui_fill( box, GUI_COL_DARK );
420 ui_outline( box, 1, GUI_COL_CLICK, 0 );
421 }
422 else if( state == k_ui_button_hover )
423 {
424 ui_fill( box, GUI_COL_NORM );
425 ui_outline( box, 1, GUI_COL_ACTIVE, 0 );
426 }
427 else
428 ui_fill( box, i==menu.main_index? GUI_COL_ACTIVE: GUI_COL_NORM );
429
430 ui_text( box, opts[i], 1, k_ui_align_middle_center, 0 );
431 }
432
433 x += box[2] + spacer;
434 }
435
436 if( vg_input.display_input_method == k_input_method_controller )
437 {
438 if( draw )
439 {
440 ui_rect inf_rb = { x, 0, 32, height };
441 ui_fill( inf_rb, rb_down? GUI_COL_NORM: GUI_COL_NORM );
442 ui_text( inf_rb, "\x92", 1, k_ui_align_middle_center, 0 );
443 }
444 x += 32;
445 }
446
447 if( draw )
448 ui_fill( (ui_rect){ x+8,0, vg.window_x-(x+8),height }, GUI_COL_NORM );
449 else
450 {
451 x = vg.window_x/2 - x/2;
452 ui_fill( (ui_rect){ 0, 0, x-8, height }, GUI_COL_NORM );
453 }
454 }
455
456 if( menu.main_index == k_menu_main_map )
457 {
458 ui_font_face( &vgf_default_large );
459 ui_rect title = { vg.window_x/2 - 512/2, height+8, 512, 64 };
460
461 ui_px x = 8,
462 y = height+8;
463
464 struct ui_vert *vs =
465 ui_fill( (ui_rect){ x,y, 0,height },
466 world_static.active_instance? GUI_COL_DARK: GUI_COL_ACTIVE );
467
468 char buf[64];
469 vg_str str;
470 vg_strnull( &str, buf, sizeof(buf) );
471 vg_strcat( &str, "Hub World" );
472
473 if( world_static.active_instance )
474 {
475 vg_strcat( &str, " (" );
476 vg_input_string( &str, input_button_list[k_srbind_mhub], 1 );
477 vg_strcatch( &str, '\x06' );
478 vg_strcatch( &str, '\x00' );
479 vg_strcat( &str, "\x1B[0m)" );
480 }
481
482 ui_px w = ui_text( (ui_rect){ x+8, y, 1000, height }, buf, 1,
483 k_ui_align_middle_left, 0 );
484 w *= vg_ui.font->sx;
485 x += w + 16;
486
487 vs[1].co[0] = x + 8;
488 vs[2].co[0] = x;
489
490 x += 2;
491
492 world_instance *world = &world_static.instances[1];
493 if( world->status == k_world_status_loaded )
494 {
495 const char *world_name =
496 mdl_pstr( &world->meta, world->info.pstr_name );
497
498 vg_strnull( &str, buf, sizeof(buf) );
499 vg_strcat( &str, world_name );
500
501 if( !world_static.active_instance &&
502 (vg_input.display_input_method == k_input_method_controller) )
503 {
504 vg_strcat( &str, " (" );
505 vg_input_string( &str, input_button_list[k_srbind_mhub], 1 );
506 vg_strcatch( &str, '\x06' );
507 vg_strcatch( &str, '\x00' );
508 vg_strcat( &str, "\x1B[0m)" );
509 }
510
511 vs = ui_fill( (ui_rect){ x,y, 1000,height },
512 world_static.active_instance? GUI_COL_ACTIVE: GUI_COL_DARK );
513 w = ui_text( (ui_rect){ x+16,y, 1000,height }, buf,
514 1, k_ui_align_middle_left, 0 );
515
516 w = w*vg_ui.font->sx + 8*3;
517 x += w;
518
519 if( button_down( k_srbind_mhub ) ||
520 ui_button_base( (ui_rect){0,y,x,height} ) == k_ui_button_click )
521 {
522 world_switch_instance( world_static.active_instance ^ 0x1 );
523 skaterift.activity = k_skaterift_default;
524 world_map.view_ready = 0;
525 }
526
527 vs[0].co[0] += 8;
528 vs[1].co[0] = x + 8;
529 vs[2].co[0] = x;
530 }
531
532 x = 8;
533 y += 8 + height;
534
535 if( world_static.active_instance )
536 {
537 ui_rect stat_panel = { x,y, 256,vg.window_y-y };
538 u32 c0 = ui_opacity( GUI_COL_DARK, 0.36f );
539 struct ui_vert *vs = ui_fill( stat_panel, c0 );
540
541 ui_rect_pad( stat_panel, (ui_px[2]){8,0} );
542
543 for( u32 i=0; i<mdl_arrcount( &world->ent_region ); i ++ )
544 {
545 ent_region *region = mdl_arritm( &world->ent_region, i );
546
547 if( !region->zone_volume )
548 continue;
549
550 const char *title = mdl_pstr( &world->meta, region->pstr_title );
551 ui_font_face( &vgf_default_large );
552
553 ui_rect title_box;
554 menu_standard_widget( stat_panel, title_box, 1 );
555
556 stat_panel[0] += 16;
557 stat_panel[2] -= 16;
558 ui_font_face( &vgf_default_small );
559
560 ent_volume *volume = mdl_arritm(&world->ent_volume,
561 mdl_entity_id_id(region->zone_volume));
562
563 u32 combined = k_ent_route_flag_achieve_gold |
564 k_ent_route_flag_achieve_silver;
565
566 char buf[128];
567 vg_str str;
568
569 for( u32 j=0; j<mdl_arrcount(&world->ent_route); j ++ )
570 {
571 ent_route *route = mdl_arritm(&world->ent_route, j );
572
573 v3f local;
574 m4x3_mulv( volume->to_local, route->board_transform[3], local );
575 if( !((fabsf(local[0]) <= 1.0f) &&
576 (fabsf(local[1]) <= 1.0f) &&
577 (fabsf(local[2]) <= 1.0f)) )
578 {
579 continue;
580 }
581
582 combined &= route->flags;
583
584 vg_strnull( &str, buf, sizeof(buf) );
585 vg_strcat( &str, mdl_pstr(&world->meta, route->pstr_name));
586
587 if( route->flags & k_ent_route_flag_achieve_silver )
588 vg_strcat( &str, " \xb3");
589 if( route->flags & k_ent_route_flag_achieve_gold )
590 vg_strcat( &str, "\xb3");
591
592 ui_rect r;
593 ui_standard_widget( stat_panel, r, 1 );
594 ui_text( r, buf, 1, k_ui_align_middle_left,
595 medal_colour(route->flags) );
596 }
597
598 for( u32 j=0; j<mdl_arrcount(&world->ent_challenge); j ++ )
599 {
600 ent_challenge *challenge = mdl_arritm( &world->ent_challenge, j );
601
602 v3f local;
603 m4x3_mulv( volume->to_local, challenge->transform.co, local );
604 if( !((fabsf(local[0]) <= 1.0f) &&
605 (fabsf(local[1]) <= 1.0f) &&
606 (fabsf(local[2]) <= 1.0f)) )
607 {
608 continue;
609 }
610
611 vg_strnull( &str, buf, sizeof(buf) );
612 vg_strcat( &str, mdl_pstr(&world->meta, challenge->pstr_alias));
613
614 u32 flags = 0x00;
615 if( challenge->status )
616 {
617 flags |= k_ent_route_flag_achieve_gold;
618 flags |= k_ent_route_flag_achieve_silver;
619 vg_strcat( &str, " \xb3\xb3" );
620 }
621
622 combined &= flags;
623
624 ui_rect r;
625 ui_standard_widget( stat_panel, r, 1 );
626 ui_text( r, buf, 1, k_ui_align_middle_left, medal_colour(flags) );
627 }
628
629 stat_panel[0] -= 16;
630 stat_panel[2] += 16;
631
632 u32 title_col = 0;
633 if( combined & k_ent_route_flag_achieve_gold )
634 title_col = ui_colour( k_ui_yellow );
635 else if( combined & k_ent_route_flag_achieve_silver )
636 title_col = ui_colour( k_ui_fg );
637
638 menu_heading( title_box, title, title_col );
639 }
640
641 vs[2].co[1] = stat_panel[1];
642 vs[3].co[1] = stat_panel[1];
643 }
644 }
645 else
646 {
647 if( button_down( k_srbind_mback ) )
648 {
649 skaterift.activity = k_skaterift_default;
650 return;
651 }
652
653 ui_rect list0 = { vg.window_x/2 - 512/2, height+32,
654 512, vg.window_y-height-64 }, list;
655 rect_copy( list0, list );
656 ui_rect_pad( list, (ui_px[2]){8,8} );
657
658 i32 *row = (i32 *[])
659 {
660 [k_menu_main_main] = &menu.main_row,
661 [k_menu_main_settings] = &menu.settings_row,
662 [k_menu_main_guide] = &menu.guides_row
663 }
664 [ menu.main_index ];
665
666 if( mv < 0 ) *row = (*row) +1;
667 if( mv > 0 ) *row = vg_max( 0, (*row) -1 );
668
669 /* MAIN / MAIN
670 * -------------------------------------------------------------------*/
671
672 if( menu.main_index == k_menu_main_main )
673 {
674 *row = vg_min( 2, *row );
675
676 if( menu_button( list, *row == 0, "Resume" ) )
677 {
678 skaterift.activity = k_skaterift_default;
679 return;
680 }
681
682 if( menu_button( list, *row == 1, "Credits" ) )
683 {
684 menu.page = k_menu_page_credits;
685 }
686
687 ui_rect end = { list[0], list[1]+list[3]-64, list[2], 72 };
688 if( menu_button( end, *row == 2, "Quit Game" ) )
689 {
690 vg.window_should_close = 1;
691 }
692 }
693 else if( menu.main_index == k_menu_main_settings )
694 {
695 ui_fill( list0, ui_opacity( GUI_COL_DARK, 0.36f ) );
696 ui_outline( list0, 1, GUI_COL_NORM, 0 );
697 *row = vg_min( 8, *row );
698
699 ui_font_face( &vgf_default_large );
700 list[1] -= 8;
701 menu_heading( list, "Game", 0 );
702 menu_checkbox( list, *row == 0, "Show controls overlay",
703 &control_overlay.enabled );
704 menu_checkbox( list, *row == 1, "Auto connect to global server",
705 &network_client.auto_connect );
706
707 menu_heading( list, "Audio/Video", 0 );
708 menu_slider( list, *row == 2, "Volume", 0, 100,
709 &vg_audio.external_global_volume, "%.f%%" );
710 menu_slider( list, *row == 3, "Resolution", 0, 100,
711 &k_render_scale, "%.f%%" );
712 menu_checkbox( list, *row == 4, "Motion Blur", &k_blur_effect );
713
714 menu_heading( list, "Camera", 0 );
715 menu_slider( list, *row == 5, "Fov", 97, 135,
716 &k_fov, "%.1f\xb0" );
717 menu_slider( list, *row == 6, "Cam Height", -0.4f, +1.4f,
718 &k_cam_height, vg_lerpf(-0.4f,1.4f,k_cam_height)>=0.0f?
719 "+%.2fm": "%.2fm" );
720 menu_checkbox( list, *row == 7, "Invert Y Axis", &k_invert_y );
721
722
723 ui_rect end = { list[0], list[1]+list[3]-64, list[2], 72 };
724 ui_font_face( &vgf_default_small );
725 menu_heading( end, "Advanced", 0 );
726 if( menu_button( end, *row == 8, "Open Engine Settings" ) )
727 {
728 vg_settings_open();
729 }
730 }
731 else if( menu.main_index == k_menu_main_guide )
732 {
733 ui_fill( list0, ui_opacity( GUI_COL_DARK, 0.36f ) );
734 ui_outline( list0, 1, GUI_COL_NORM, 0 );
735 *row = vg_min( 4, *row );
736
737 ui_font_face( &vgf_default_large );
738 list[1] -= 8;
739 menu_heading( list, "Controls", 0 );
740 if( menu_button( list, *row == 0, "Skating \xb2" ) )
741 {
742 }
743 if( menu_button( list, *row == 1, "Tricks \xb2" ) )
744 {
745 }
746
747 menu_heading( list, "Workshop", 0 );
748 if( menu_button( list, *row == 2, "Create a Board \xb2" ) )
749 {
750 }
751 if( menu_button( list, *row == 3, "Create a World \xb2" ) )
752 {
753 }
754 if( menu_button( list, *row == 4, "Create a Playermodel \xb2" ) )
755 {
756 }
757 }
758 }
759
760 menu_draw:
761
762 vg_ui.frosting = 0.015f;
763 ui_flush( k_ui_shader_colour, vg.window_x, vg.window_y );
764 vg_ui.frosting = 0.0f;
765
766 ui_font_face( &vgf_default_small );
767 }