diff --git a/README.md b/README.md index e69de29..6dbfd3b 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,28 @@ +# Scan3D Vulkan + +Scan3D Vulkan est une application terminal interactive dédiée à la reconstruction 3D. Cette première interface TUI utilise tout l'espace du terminal et s'adapte à son redimensionnement. + +Une vue Vulkan séparée sera ajoutée ultérieurement pour afficher la scène 3D. L'application actuelle n'ouvre aucune fenêtre graphique. + +## Prérequis + +- Arch Linux (ou distribution dérivée) +- Clang +- Meson +- Ninja +- ncursesw + +## Compilation + +```sh +CC=clang meson setup build --wipe +meson compile -C build -j8 +``` + +## Exécution + +```sh +./build/scan3d-vulkan +``` + +La TUI s'affiche directement dans le terminal courant. Appuyez sur `q` ou `Q` pour quitter proprement. diff --git a/include/scan3d/app.h b/include/scan3d/app.h new file mode 100644 index 0000000..729aee3 --- /dev/null +++ b/include/scan3d/app.h @@ -0,0 +1,14 @@ +#ifndef SCAN3D_APP_H +#define SCAN3D_APP_H + +#ifdef __cplusplus +extern "C" { +#endif + +int scan3d_app_run(void); + +#ifdef __cplusplus +} +#endif + +#endif /* SCAN3D_APP_H */ diff --git a/include/scan3d/tui.h b/include/scan3d/tui.h new file mode 100644 index 0000000..21058a4 --- /dev/null +++ b/include/scan3d/tui.h @@ -0,0 +1,18 @@ +#ifndef SCAN3D_TUI_H +#define SCAN3D_TUI_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool scan3d_tui_init(void); +bool scan3d_tui_run(void); +void scan3d_tui_shutdown(void); + +#ifdef __cplusplus +} +#endif + +#endif /* SCAN3D_TUI_H */ diff --git a/meson.build b/meson.build index e69de29..66926d4 100644 --- a/meson.build +++ b/meson.build @@ -0,0 +1,31 @@ +project( + 'scan3d-vulkan', + 'c', + version: '0.1.0', + license: 'MIT', + default_options: [ + 'c_std=c17', + 'warning_level=3', + 'buildtype=debugoptimized', + ], +) + +add_project_arguments( + '-Wpedantic', + '-Wconversion', + '-Wshadow', + language: 'c', +) + +ncursesw = dependency('ncursesw', required: true) + +executable( + 'scan3d-vulkan', + sources: [ + 'src/main.c', + 'src/app.c', + 'src/tui.c', + ], + include_directories: include_directories('include'), + dependencies: [ncursesw], +) diff --git a/src/app.c b/src/app.c new file mode 100644 index 0000000..e8bf0bb --- /dev/null +++ b/src/app.c @@ -0,0 +1,17 @@ +#include + +#include +#include + +int +scan3d_app_run(void) +{ + if (!scan3d_tui_init()) { + return EXIT_FAILURE; + } + + bool success = scan3d_tui_run(); + scan3d_tui_shutdown(); + + return success ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..8904ed1 --- /dev/null +++ b/src/main.c @@ -0,0 +1,7 @@ +#include + +int +main(void) +{ + return scan3d_app_run(); +} diff --git a/src/tui.c b/src/tui.c new file mode 100644 index 0000000..ac79f45 --- /dev/null +++ b/src/tui.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include + +#include + +static void +draw_centered(int row, int rows, int columns, const char *text) +{ + if (row < 0 || row >= rows || columns <= 2) { + return; + } + + int length = (int)strlen(text); + int available = columns - 2; + int displayed = length < available ? length : available; + int column = (columns - displayed) / 2; + + (void)mvaddnstr(row, column, text, displayed); +} + +static bool +draw_interface(void) +{ + int rows; + int columns; + getmaxyx(stdscr, rows, columns); + + if (erase() == ERR) { + return false; + } + + if (rows >= 2 && columns >= 2) { + (void)box(stdscr, 0, 0); + } + + draw_centered(1, rows, columns, "Scan3D Vulkan"); + draw_centered(3, rows, columns, "Projet de reconstruction 3D"); + + char dimensions[64]; + (void)snprintf( + dimensions, + sizeof(dimensions), + "Terminal : %d x %d", + columns, + rows + ); + draw_centered(5, rows, columns, dimensions); + draw_centered(rows - 2, rows, columns, "q : quitter"); + + return refresh() != ERR; +} + +bool +scan3d_tui_init(void) +{ + if (!initscr()) { + return false; + } + + if (cbreak() == ERR || noecho() == ERR || keypad(stdscr, true) == ERR + || curs_set(0) == ERR) { + endwin(); + return false; + } + + return true; +} + +bool +scan3d_tui_run(void) +{ + if (!draw_interface()) { + return false; + } + + for (;;) { + int key = getch(); + if (key == 'q' || key == 'Q') { + return true; + } + if (key == ERR) { + return false; + } + if (key == KEY_RESIZE && !draw_interface()) { + return false; + } + } +} + +void +scan3d_tui_shutdown(void) +{ + endwin(); +}