From 3eef29c327abd46e73c0a4d5b1c186dd7d3878b2 Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Romero Date: Tue, 20 Sep 2022 17:28:35 +0200 Subject: [PATCH] menu: Implement join_menu --- src/gui/CMakeLists.txt | 2 +- src/menu/CMakeLists.txt | 1 + src/menu/privinc/menu_private.h | 1 + src/menu/src/hostjoin_menu.c | 9 +- src/menu/src/join_menu.c | 262 ++++++++++++++++++++++++++++++++ src/menu/src/settings_menu.c | 62 ++++++++ src/system/CMakeLists.txt | 2 +- src/system/ps1/src/init.c | 4 +- src/system/sdl-1.2/src/system.c | 4 +- 9 files changed, 342 insertions(+), 5 deletions(-) create mode 100644 src/menu/src/join_menu.c create mode 100644 src/menu/src/settings_menu.c diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index f96d927..504c02f 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -10,4 +10,4 @@ add_library(gui "src/rounded_rect.c" ) target_include_directories(gui PUBLIC "inc" PRIVATE "privinc") -target_link_libraries(gui PUBLIC camera gfx input peripheral font) +target_link_libraries(gui PUBLIC camera gfx input net peripheral font) diff --git a/src/menu/CMakeLists.txt b/src/menu/CMakeLists.txt index 940b26b..465250f 100644 --- a/src/menu/CMakeLists.txt +++ b/src/menu/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(menu "src/gamecfg_menu.c" "src/hostjoin_menu.c" + "src/join_menu.c" "src/menu.c" "src/main_menu.c" ) diff --git a/src/menu/privinc/menu_private.h b/src/menu/privinc/menu_private.h index 0276b20..181825c 100644 --- a/src/menu/privinc/menu_private.h +++ b/src/menu/privinc/menu_private.h @@ -24,6 +24,7 @@ int menu_update(struct menu_common *c, void *arg); int menu_main(struct menu_common *c); int menu_hostjoin(struct menu_common *c, bool *back); +int menu_join(struct menu_common *c); int menu_gamecfg(struct menu_common *c); void menu_on_pressed(void *arg); diff --git a/src/menu/src/hostjoin_menu.c b/src/menu/src/hostjoin_menu.c index 49d5ec9..9ce93b1 100644 --- a/src/menu/src/hostjoin_menu.c +++ b/src/menu/src/hostjoin_menu.c @@ -75,9 +75,16 @@ int menu_hostjoin(struct menu_common *const c, bool *const back) return -1; } - if (host || join) + if (host) + { if (menu_gamecfg(c)) return -1; + } + else if (join) + { + if (menu_join(c)) + return -1; + } } while (!*back && !c->p.common.exit); diff --git a/src/menu/src/join_menu.c b/src/menu/src/join_menu.c new file mode 100644 index 0000000..40b0f4e --- /dev/null +++ b/src/menu/src/join_menu.c @@ -0,0 +1,262 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct join_menu +{ + struct gui_container cnt, bcnt; + struct gui_label type_label, address, port, connecting; + struct gui_button type_btn, back, connect; + struct gui_line_edit address_le, port_le; + + enum + { + IDLE, + CONNECT, + CONNECTING, + CONNECTED, + CONNECT_FAILED + } state; + + struct net_socket *socket; + size_t domain_i; +}; + +static const enum net_domain domains[] = +{ + NET_DOMAIN_IPV4, + NET_DOMAIN_SERIAL +}; + +static void on_connected(void *const arg) +{ + struct join_menu *const m = arg; + + if (m->state == IDLE) + { + m->state = CONNECT; + m->connecting.text = "Connecting..."; + } +} + +static void on_disconnected(void *const arg) +{ + struct join_menu *const m = arg; + + m->connecting.text = "Failed to connect"; + m->state = CONNECT_FAILED; + m->socket = NULL; +} + +static int on_connect(struct join_menu *const m) +{ + const enum net_domain d = domains[m->domain_i]; + + union net_connect c = + { + .common = + { + .domain = d, + .on_connected = on_connected, + .on_disconnected = on_disconnected, + .arg = m + } + }; + + switch (d) + { + case NET_DOMAIN_IPV4: + { + errno = 0; + + const unsigned long port = strtoul(m->port_le.text, NULL, 0); + + if (errno) + return -1; + + c.ipv4.addr = m->address_le.text; + c.ipv4.port = port; + } + break; + + case NET_DOMAIN_SERIAL: + break; + } + + if (!(m->socket = net_connect(&c))) + { + fprintf(stderr, "%s: net_connect failed\n", __func__); + return -1; + } + + return 0; +} + +static int update(struct menu_common *const c, void *const arg) +{ + struct join_menu *const m = arg; + + m->bcnt.common.y = screen_h - 40; + + if (gui_update(&m->cnt.common, &c->p, &c->cam, &c->in) + || gui_update(&m->bcnt.common, &c->p, &c->cam, &c->in)) + return -1; + + if (m->socket && net_update(m->socket)) + return -1; + + switch (m->state) + { + case CONNECT: + if (on_connect(m)) + return -1; + + m->state = CONNECTING; + + if (!m->connecting.common.parent) + gui_add_child(&m->cnt.common, &m->connecting.common); + + break; + + case CONNECT_FAILED: + net_close(m->socket); + m->socket = NULL; + m->state = IDLE; + break; + + default: + break; + } + + return 0; +} + +static int render(const struct menu_common *const c, void *const arg) +{ + const struct join_menu *const m = arg; + + if (gui_render(&m->cnt.common) + || gui_render(&m->bcnt.common)) + return -1; + + return 0; +} + +static void on_type_pressed(void *const arg) +{ + struct join_menu *const m = arg; + + if (++m->domain_i >= sizeof domains / sizeof *domains) + m->domain_i = 0; + + m->type_btn.u.type1.label.text = net_domain_str(domains[m->domain_i]); +} + +static void on_connect_pressed(void *const arg) +{ + struct join_menu *const m = arg; + + m->state = CONNECT; +} + +int menu_join(struct menu_common *const c) +{ + int ret = -1; + struct join_menu m = {0}; + bool connect = false; + bool back = false; + + gui_container_init(&m.cnt); + m.cnt.common.hcentered = true; + m.cnt.common.vcentered = true; + m.cnt.mode = GUI_CONTAINER_MODE_V; + m.cnt.spacing = 2; + + gui_label_init(&m.type_label); + m.type_label.common.hcentered = true; + m.type_label.text = "Type:"; + gui_add_child(&m.cnt.common, &m.type_label.common); + + gui_button_init(&m.type_btn, GUI_BUTTON_TYPE_1); + m.type_btn.arg = &m; + m.type_btn.u.type1.w = 140; + m.type_btn.common.hcentered = true; + m.type_btn.on_pressed = on_type_pressed; + m.type_btn.u.type1.label.text = net_domain_str(*domains); + gui_add_child(&m.cnt.common, &m.type_btn.common); + + gui_label_init(&m.address); + m.address.common.hcentered = true; + m.address.text = "Address:"; + gui_add_child(&m.cnt.common, &m.address.common); + + char address[sizeof "255.255.255.255"]; + gui_line_edit_init(&m.address_le, address, sizeof address); + m.address_le.w = 140; + m.address_le.common.hcentered = true; + gui_add_child(&m.cnt.common, &m.address_le.common); + + gui_label_init(&m.port); + m.port.common.hcentered = true; + m.port.text = "Port:"; + gui_add_child(&m.cnt.common, &m.port.common); + + char port[sizeof "65535"]; + gui_line_edit_init(&m.port_le, port, sizeof port); + m.port_le.w = 80; + m.port_le.common.hcentered = true; + gui_add_child(&m.cnt.common, &m.port_le.common); + + gui_label_init(&m.connecting); + m.connecting.common.hcentered = true; + + gui_container_init(&m.bcnt); + m.bcnt.common.hcentered = true; + m.bcnt.mode = GUI_CONTAINER_MODE_H; + + gui_button_init(&m.connect, GUI_BUTTON_TYPE_1); + m.connect.u.type1.label.text = "Connect"; + m.connect.u.type1.w = 140; + m.connect.common.vcentered = true; + m.connect.on_pressed = on_connect_pressed; + m.connect.arg = &m; + m.back.common.vcentered = true; + gui_add_child(&m.bcnt.common, &m.connect.common); + + gui_button_init(&m.back, GUI_BUTTON_TYPE_1); + m.back.u.type1.label.text = "Back"; + m.back.u.type1.w = 100; + m.back.common.vcentered = true; + m.back.on_pressed = menu_on_pressed; + m.back.arg = &back; + m.back.common.vcentered = true; + gui_add_child(&m.bcnt.common, &m.back.common); + + while (!back && !c->p.common.exit && !connect) + { + if (menu_update(c, update, render, &m)) + goto end; + } + + if (connect) + { + + } + + ret = 0; + +end: + gui_deinit(&m.cnt.common, &c->in); + return ret; +} diff --git a/src/menu/src/settings_menu.c b/src/menu/src/settings_menu.c new file mode 100644 index 0000000..0e782bd --- /dev/null +++ b/src/menu/src/settings_menu.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include +#include + +struct menu_settings +{ + struct gui_container cnt; + struct gui_button back; +}; + +static int update(struct menu_common *const c, void *const arg) +{ + struct menu_settings *const m = arg; + + if (gui_update(&m->cnt.common, &c->p, &c->cam, &c->in)) + return -1; + + return 0; +} + +static int render(const struct menu_common *const c, void *const arg) +{ + const struct menu_settings *const m = arg; + + if (gui_render(&m->cnt.common)) + return -1; + + return 0; +} + +int menu_settings(struct menu_common *const c, bool *const back) +{ + do + { + struct menu_settings m; + + gui_container_init(&m.cnt); + m.cnt.common.hcentered = true; + m.cnt.common.vcentered = true; + m.cnt.spacing = 4; + m.cnt.mode = GUI_CONTAINER_MODE_V; + + gui_button_init(&m.back, GUI_BUTTON_TYPE_1); + m.back.u.type1.label.text = "Back"; + m.back.common.hcentered = true; + m.back.u.type1.w = 140; + m.back.arg = back; + m.back.on_pressed = menu_on_pressed; + gui_add_child(&m.cnt.common, &m.back.common); + + while (!*back && !c->p.common.exit) + if (menu_update(c, update, render, &m)) + return -1; + + } while (!*back && !c->p.common.exit); + + return 0; +} diff --git a/src/system/CMakeLists.txt b/src/system/CMakeLists.txt index 011aee6..4c315b9 100644 --- a/src/system/CMakeLists.txt +++ b/src/system/CMakeLists.txt @@ -1,5 +1,5 @@ set(inc "inc") -set(privdeps gfx sfx) +set(privdeps gfx sfx net) if(PS1_BUILD) set(src "ps1/src/init.c") diff --git a/src/system/ps1/src/init.c b/src/system/ps1/src/init.c index 4c30fbd..4ad12c2 100644 --- a/src/system/ps1/src/init.c +++ b/src/system/ps1/src/init.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -20,13 +21,14 @@ void system_deinit(void) { gfx_deinit(); sfx_deinit(); + net_deinit(); } int system_init(void) { SetVBlankHandler(vblank); - if (gfx_init() || sfx_init()) + if (gfx_init() || sfx_init() || net_init()) return -1; return 0; diff --git a/src/system/sdl-1.2/src/system.c b/src/system/sdl-1.2/src/system.c index 24c3e18..bff5e4f 100644 --- a/src/system/sdl-1.2/src/system.c +++ b/src/system/sdl-1.2/src/system.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -19,6 +20,7 @@ void system_deinit(void) { gfx_deinit(); sfx_deinit(); + net_deinit(); SDL_Quit(); } @@ -29,7 +31,7 @@ int system_init(void) fprintf(stderr, "SDL_Init: %s\n", SDL_GetError()); goto failure; } - else if (gfx_init() || sfx_init()) + else if (gfx_init() || sfx_init() || net_init()) goto failure; SDL_WM_SetCaption("rts", NULL);