add strip for hub switch to 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 "shaders/model_menu.h"
13
14 struct global_menu menu = { .skip_starter = 0 };
15
16 void menu_at_begin(void)
17 {
18 if( menu.skip_starter ) return;
19
20 skaterift.activity = k_skaterift_menu;
21 menu.page = k_menu_page_starter;
22 }
23
24 void menu_init(void)
25 {
26 vg_console_reg_var( "skip_starter_menu", &menu.skip_starter,
27 k_var_dtype_i32, VG_VAR_PERSISTENT );
28 }
29
30 void menu_open( enum menu_page page )
31 {
32 skaterift.activity = k_skaterift_menu;
33
34 if( page != k_menu_page_any )
35 {
36 menu.page = page;
37 }
38 }
39
40 bool menu_viewing_map(void)
41 {
42 return (skaterift.activity == k_skaterift_menu) &&
43 (menu.page == k_menu_page_main) &&
44 (menu.main_index == k_menu_main_map);
45 }
46
47 void menu_gui(void)
48 {
49 if( button_down( k_srbind_mopen ) )
50 {
51 if( skaterift.activity == k_skaterift_default )
52 {
53 menu_open( k_menu_page_main );
54 return;
55 }
56 }
57
58 if( skaterift.activity != k_skaterift_menu )
59 return;
60
61 /* get buttons inputs
62 * -------------------------------------------------------------------*/
63 int ml = button_down( k_srbind_mleft ),
64 mr = button_down( k_srbind_mright ),
65 mu = button_down( k_srbind_mup ),
66 md = button_down( k_srbind_mdown ),
67 mh = ml-mr,
68 mv = mu-md,
69 enter = button_down( k_srbind_maccept );
70
71 if( mh||mv||enter )
72 {
73 menu.input_mode = k_menu_input_mode_keys;
74 }
75
76 /* get mouse inputs
77 * --------------------------------------------------------------------*/
78 menu.mouse_dist += v2_length( vg.mouse_delta ); /* TODO: Move to UI */
79 if( menu.mouse_dist > 10.0f )
80 {
81 menu.input_mode = k_menu_input_mode_mouse;
82 menu.mouse_dist = 0.0f;
83 }
84
85 if( ui_clicking(UI_MOUSE_LEFT) || ui_clicking(UI_MOUSE_RIGHT) )
86 {
87 menu.input_mode = k_menu_input_mode_mouse;
88 }
89
90 if( menu.input_mode == k_menu_input_mode_mouse )
91 {
92 /*
93 * handle mouse input
94 * ------------------------------------------------------------*/
95 vg_ui.wants_mouse = 1;
96 }
97
98 if( skaterift.activity != k_skaterift_menu ) return;
99
100
101 /* TOP BAR
102 * -------------------------------------------------------------------*/
103
104 ui_font_face( &vgf_default_title );
105 ui_px height = vg_ui.font->ch + 16;
106 ui_rect topbar = { 0, 0, vg.window_x, height };
107
108 const char *opts[] = {
109 [k_menu_main_main] = "Menu",
110 [k_menu_main_map] = "Map"
111 };
112
113 /* TAB CONTROL */
114 u8 lb_down = 0, rb_down = 0;
115 vg_exec_input_program( k_vg_input_type_button_u8,
116 (vg_input_op[]){
117 vg_joy_button, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, vg_end
118 }, &rb_down );
119 vg_exec_input_program( k_vg_input_type_button_u8,
120 (vg_input_op[]){
121 vg_joy_button, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, vg_end
122 }, &lb_down );
123
124 if( menu.repeater > 0.0f )
125 {
126 menu.repeater -= vg_minf( vg.time_frame_delta, 0.5f );
127 }
128 else
129 {
130 if( lb_down != rb_down )
131 {
132 menu.main_index += rb_down;
133 menu.main_index -= lb_down;
134 menu.repeater += 0.2f;
135
136 if( menu.main_index == -1 )
137 menu.main_index ++;
138
139 if( menu.main_index == vg_list_size(opts) )
140 menu.main_index --;
141 }
142 }
143
144 ui_px x = 0,
145 spacer = 8;
146 for( u32 draw=0; draw<2; draw ++ )
147 {
148 if( draw )
149 {
150 ui_rect inf_lb = { x, 0, 32, height };
151 ui_fill( inf_lb, lb_down? GUI_COL_NORM: GUI_COL_NORM );
152 ui_text( inf_lb, "\x91", 1, k_ui_align_middle_center, 0 );
153 }
154 x += 32 + spacer;
155
156 for( i32 i=0; i<vg_list_size(opts); i ++ )
157 {
158 ui_rect box = { x, 0, ui_text_line_width(opts[i]) + 32, height };
159
160 if( draw )
161 {
162 enum ui_button_state state = ui_button_base( box );
163 if( state == k_ui_button_click )
164 {
165 ui_fill( box, GUI_COL_DARK );
166 menu.main_index = i;
167 }
168 else if( state == k_ui_button_holding_inside )
169 {
170 ui_fill( box, GUI_COL_DARK );
171 }
172 else if( state == k_ui_button_holding_outside )
173 {
174 ui_fill( box, GUI_COL_DARK );
175 ui_outline( box, 1, GUI_COL_CLICK, 0 );
176 }
177 else if( state == k_ui_button_hover )
178 {
179 ui_fill( box, GUI_COL_NORM );
180 ui_outline( box, 1, GUI_COL_ACTIVE, 0 );
181 }
182 else
183 ui_fill( box, i==menu.main_index? GUI_COL_ACTIVE: GUI_COL_NORM );
184
185 ui_text( box, opts[i], 1, k_ui_align_middle_center, 0 );
186 }
187
188 x += box[2] + spacer;
189 }
190
191 if( draw )
192 {
193 ui_rect inf_rb = { x, 0, 32, height };
194 ui_fill( inf_rb, rb_down? GUI_COL_NORM: GUI_COL_NORM );
195 ui_text( inf_rb, "\x92", 1, k_ui_align_middle_center, 0 );
196 }
197 x += 32;
198
199 if( draw )
200 ui_fill( (ui_rect){ x+8,0, vg.window_x-(x+8),height }, GUI_COL_NORM );
201 else
202 {
203 x = vg.window_x/2 - x/2;
204 ui_fill( (ui_rect){ 0, 0, x-8, height }, GUI_COL_NORM );
205 }
206 }
207
208 if( menu.main_index == k_menu_main_map )
209 {
210 ui_font_face( &vgf_default_large );
211 ui_rect title = { vg.window_x/2 - 512/2, height+8, 512, 64 };
212
213 ui_px x = 8,
214 y = height+8;
215
216 struct ui_vert *vs =
217 ui_fill( (ui_rect){ x,y, 0,height },
218 world_static.active_instance? GUI_COL_DARK: GUI_COL_ACTIVE );
219
220 char buf[64];
221 vg_str str;
222 vg_strnull( &str, buf, sizeof(buf) );
223 vg_strcat( &str, "Hub World" );
224
225 if( world_static.active_instance &&
226 (vg_input.display_input_method == k_input_method_controller) )
227 {
228 vg_strcat( &str, " (" );
229 vg_input_string( &str, input_button_list[k_srbind_mhub], 1 );
230 vg_strcat( &str, ")" );
231 }
232
233 ui_px w = ui_text( (ui_rect){ x+8, y, 1000, height }, buf, 1,
234 k_ui_align_middle_left, 0 );
235 w *= vg_ui.font->sx;
236 x += w + 16;
237
238 vs[1].co[0] = x + 8;
239 vs[2].co[0] = x;
240
241 x += 2;
242
243 world_instance *world = &world_static.instances[1];
244 if( world->status == k_world_status_loaded )
245 {
246 const char *world_name =
247 mdl_pstr( &world->meta, world->info.pstr_name );
248
249 vg_strnull( &str, buf, sizeof(buf) );
250 vg_strcat( &str, world_name );
251
252 if( !world_static.active_instance &&
253 (vg_input.display_input_method == k_input_method_controller) )
254 {
255 vg_strcat( &str, " (" );
256 vg_input_string( &str, input_button_list[k_srbind_mhub], 1 );
257 vg_strcat( &str, ")" );
258 }
259
260 vs = ui_fill( (ui_rect){ x,y, 1000,height },
261 world_static.active_instance? GUI_COL_ACTIVE: GUI_COL_DARK );
262 w = ui_text( (ui_rect){ x+16,y, 1000,height }, buf,
263 1, k_ui_align_middle_left, 0 );
264
265 w = w*vg_ui.font->sx + 8*3;
266 x += w;
267
268 if( button_down( k_srbind_mhub ) ||
269 ui_button_base( (ui_rect){0,y,x,height} ) == k_ui_button_click )
270 {
271 world_switch_instance( world_static.active_instance ^ 0x1 );
272 skaterift.activity = k_skaterift_default;
273 world_map.view_ready = 0;
274 }
275
276 vs[0].co[0] += 8;
277 vs[1].co[0] = x + 8;
278 vs[2].co[0] = x;
279 }
280 }
281 else
282 {
283 if( button_down( k_srbind_mback ) )
284 {
285 skaterift.activity = k_skaterift_default;
286 return;
287 }
288 }
289
290 /* MAIN / MAIN
291 * -------------------------------------------------------------------*/
292
293 if( menu.main_index == k_menu_main_main )
294 {
295 ui_rect list = { vg.window_x/2 - 512/2, height+64,
296 512, vg.window_y-height-128 };
297 ui_fill( list, GUI_COL_DARK );
298 }
299
300 vg_ui.frosting = 0.015f;
301 ui_flush( k_ui_shader_colour, vg.window_x, vg.window_y );
302 vg_ui.frosting = 0.0f;
303
304 ui_font_face( &vgf_default_small );
305 }