diff --git a/CMakeLists.txt b/CMakeLists.txt index 17f8ddf..e114592 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,4 +16,3 @@ add_subdirectory(program) include(CTest) enable_testing() add_subdirectory(test) - diff --git a/cmake/UpdateSubmodules.cmake b/cmake/UpdateSubmodules.cmake index 1630412..d798c30 100644 --- a/cmake/UpdateSubmodules.cmake +++ b/cmake/UpdateSubmodules.cmake @@ -18,4 +18,4 @@ if(GIT_FOUND) return() endif() message(STATUS "Git submodules updated successfully") -endif() \ No newline at end of file +endif() diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 2043bab..cae805c 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -2,7 +2,7 @@ add_library(greatest INTERFACE "") target_include_directories(greatest INTERFACE greatest) add_library(nuklear INTERFACE "") -target_include_directories(nuklear INTERFACE nuklear nuklear/demo/glfw_opengl3) +target_include_directories(nuklear INTERFACE nuklear nuklear/demo/glfw_opengl3 nuklear/example) set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) diff --git a/program/CMakeLists.txt b/program/CMakeLists.txt index 70bd018..29516af 100644 --- a/program/CMakeLists.txt +++ b/program/CMakeLists.txt @@ -28,10 +28,10 @@ add_library(program source/slnoslav.c ) -#target_compile_definitions(program PRIVATE ERROR_LOG_FILE_PATH=\"${CMAKE_BINARY_DIR}/debug_log.txt\") - target_include_directories(program PUBLIC include) +target_compile_definitions(program PRIVATE ERROR_LOG_FILE_PATH=\"${CMAKE_BINARY_DIR}/debug_log.txt\") + target_link_libraries(program PRIVATE glfw PRIVATE libglew_static diff --git a/program/assets/icons/backwards.png b/program/assets/icons/backwards.png new file mode 100644 index 0000000..bf1c13f Binary files /dev/null and b/program/assets/icons/backwards.png differ diff --git a/program/assets/icons/end.png b/program/assets/icons/end.png new file mode 100644 index 0000000..4ba6a23 Binary files /dev/null and b/program/assets/icons/end.png differ diff --git a/program/assets/icons/forwards.png b/program/assets/icons/forwards.png new file mode 100644 index 0000000..dfc8214 Binary files /dev/null and b/program/assets/icons/forwards.png differ diff --git a/program/assets/icons/next.png b/program/assets/icons/next.png new file mode 100644 index 0000000..ab091a8 Binary files /dev/null and b/program/assets/icons/next.png differ diff --git a/program/assets/icons/previous.png b/program/assets/icons/previous.png new file mode 100644 index 0000000..5812dbf Binary files /dev/null and b/program/assets/icons/previous.png differ diff --git a/program/assets/icons/start.png b/program/assets/icons/start.png new file mode 100644 index 0000000..be0e4d9 Binary files /dev/null and b/program/assets/icons/start.png differ diff --git a/program/assets/icons/stop.png b/program/assets/icons/stop.png new file mode 100644 index 0000000..22911a2 Binary files /dev/null and b/program/assets/icons/stop.png differ diff --git a/program/include/gui/default.h b/program/include/gui/default.h index f06f180..281a41b 100644 --- a/program/include/gui/default.h +++ b/program/include/gui/default.h @@ -14,7 +14,7 @@ #include #define WINDOW_WIDTH 500 -#define WINDOW_HEIGHT 560 +#define WINDOW_HEIGHT 500 #define MAX_VERTEX_BUFFER 512 * 1024 #define MAX_ELEMENT_BUFFER 128 * 1024 @@ -23,9 +23,20 @@ struct nk_solver { board_s board; }; +struct nk_media { + struct nk_image play; + struct nk_image pause; + struct nk_image previous; + struct nk_image next; + struct nk_image begin; + struct nk_image end; + struct nk_image reverse; +}; + struct nk_super { struct nk_context * context; struct nk_solver solver; + struct nk_media media; }; #endif /* GUI_DEFAULT_H */ \ No newline at end of file diff --git a/program/include/instance/settings.h b/program/include/instance/settings.h index 9b126aa..41f9c6b 100644 --- a/program/include/instance/settings.h +++ b/program/include/instance/settings.h @@ -4,6 +4,7 @@ #include #include +#define MAX_DELAY_MS 500 typedef struct settings { char * filepath; diff --git a/program/source/algorithms/arc_consistency.c b/program/source/algorithms/arc_consistency.c index efc704b..9cdb7b0 100644 --- a/program/source/algorithms/arc_consistency.c +++ b/program/source/algorithms/arc_consistency.c @@ -30,8 +30,7 @@ bool look_ahead(const board_s board, state_array_s * current_state) { error_mode = ASSERT_E; expect(current_state, NO_ACTION, "ERROR: current state parameter is NULL (%p)", (void*)current_state); - error_mode = DEFAULT_E; - expect(get_settings_singleton()->is_arc_consistency, return true, "WARNING: arc consistency is off"); + if (!get_settings_singleton()->is_arc_consistency) return true; get_stat_singleton()->look_ahead_call_count++; diff --git a/program/source/algorithms/backtrack.c b/program/source/algorithms/backtrack.c index 131a32e..11b87eb 100644 --- a/program/source/algorithms/backtrack.c +++ b/program/source/algorithms/backtrack.c @@ -18,8 +18,7 @@ bool _backtrack_row_repeat(board_s board, state_array_s current_state, size_t in bool _backtrack_col_repeat(board_s board, state_array_s current_state, size_t index); bool backtrack(board_s board, state_array_s current_state) { - error_mode = DEFAULT_E; - expect(get_settings_singleton()->is_backtrack, return _backtrack_valid_sums(board, current_state), "WARNING: backtracking is off"); + if (!get_settings_singleton()->is_backtrack) return _backtrack_valid_sums(board, current_state); get_stat_singleton()->backtrack_call_count++; diff --git a/program/source/algorithms/forward_checking.c b/program/source/algorithms/forward_checking.c index 6437ad6..f9e9447 100644 --- a/program/source/algorithms/forward_checking.c +++ b/program/source/algorithms/forward_checking.c @@ -14,8 +14,7 @@ bool forward_checking(board_s board, state_array_s * current_state, ulookup_t in expect(is_one_value(current_state->elements[index]), NO_ACTION, "current state element at index %u is not a one value", index); expect(index < current_state->size, NO_ACTION, "index '%u' is out of bounds of current state size '%u'", index, current_state->size); - error_mode = DEFAULT_E; - expect(get_settings_singleton()->is_forward_check, return true, "WARNING: forward checking is off"); + if (!get_settings_singleton()->is_forward_check) return true; get_stat_singleton()->forward_check_call_count++; diff --git a/program/source/gui/graphics.c b/program/source/gui/graphics.c index 2ff7f41..f8e6086 100644 --- a/program/source/gui/graphics.c +++ b/program/source/gui/graphics.c @@ -26,6 +26,9 @@ #include #include +#define STB_IMAGE_IMPLEMENTATION +#include + static void error_callback(int number, const char * description) { error_mode = ASSERT_E; expect(NULL, NO_ACTION, "Error %d: %s\n", number, description); @@ -35,6 +38,8 @@ void _glew_initialize(void); void _glfw_initialize(GLFWwindow ** window, int * width, int * height); struct nk_super _create_super(struct nk_glfw * glfw, GLFWwindow * window); void _destroy_super(struct nk_super * super); +struct nk_media _create_media(void); +struct nk_image icon_load(const char *filename); void gui(void) { struct nk_glfw glfw = { 0 }; @@ -51,6 +56,7 @@ void gui(void) { interface(&super); draw(&glfw); } + _destroy_super(&super); nk_glfw3_shutdown(&glfw); glfwTerminate(); @@ -91,14 +97,52 @@ struct nk_super _create_super(struct nk_glfw * glfw, GLFWwindow * window) { board_s board = create_board(fp); fclose(fp); + struct nk_media media = _create_media(); + return (struct nk_super) { .context = context, .solver = { .board = board, }, + .media = media, }; } void _destroy_super(struct nk_super * super) { destroy_board(&super->solver.board); +} + +struct nk_media _create_media(void) { + glEnable(GL_TEXTURE_2D); + + struct nk_media media = { 0 }; + media.play = icon_load("./program/assets/icons/forwards.png"); + media.pause = icon_load("./program/assets/icons/stop.png"); + media.begin = icon_load("./program/assets/icons/start.png"); + media.end = icon_load("./program/assets/icons/end.png"); + media.reverse = icon_load("./program/assets/icons/backwards.png"); + media.next = icon_load("./program/assets/icons/next.png"); + media.previous = icon_load("./program/assets/icons/previous.png"); + + return media; +} + +struct nk_image icon_load(const char *filename) { + int x,y,n; + GLuint tex; + unsigned char *data = stbi_load(filename, &x, &y, &n, 0); + + error_mode = ASSERT_E; + expect(data, NO_ACTION, "[ERROR]: failed to load image: %s", filename); + + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + glGenerateMipmap(GL_TEXTURE_2D); + stbi_image_free(data); + return nk_image_id((int)tex); } \ No newline at end of file diff --git a/program/source/gui/interface/interface.c b/program/source/gui/interface/interface.c index a444cc2..f6a662a 100644 --- a/program/source/gui/interface/interface.c +++ b/program/source/gui/interface/interface.c @@ -2,13 +2,17 @@ #include #include -void _player(struct nk_context * context); -void _to_start(struct nk_context * context); -void _previus(struct nk_context * context); -void _playback(struct nk_context * context); -void _play(struct nk_context * context); -void _next(struct nk_context * context); -void _to_end(struct nk_context * context); +#include + +#include + +void _player(struct nk_context * context, struct nk_media media); +void _to_start(struct nk_context * context, struct nk_image image); +void _previus(struct nk_context * context, struct nk_image image); +void _playback(struct nk_context * context, struct nk_image play, struct nk_image stop); +void _play(struct nk_context * context, struct nk_image play, struct nk_image stop); +void _next(struct nk_context * context, struct nk_image image); +void _to_end(struct nk_context * context, struct nk_image image); void interface(struct nk_super * super) { struct nk_context * context = super->context; @@ -16,67 +20,80 @@ void interface(struct nk_super * super) { if (nk_begin(super->context, "KAKURO BOARD", nk_rect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT), NK_WINDOW_BORDER)) { grid(context, board); - _player(context); + _player(context, super->media); } nk_end(super->context); } -void _player(struct nk_context * context) { - nk_layout_row_dynamic(context, 50, 6); - _to_start(context); - _previus(context); - _playback(context); - _play(context); - _next(context); - _to_end(context); +void _player(struct nk_context * context, struct nk_media media) { + nk_layout_row_template_begin(context, 50); + + nk_layout_row_template_push_static(context, 50); + nk_layout_row_template_push_static(context, 50); + nk_layout_row_template_push_static(context, 50); + nk_layout_row_template_push_static(context, 50); + nk_layout_row_template_push_static(context, 50); + nk_layout_row_template_push_static(context, 50); + nk_layout_row_template_push_dynamic(context); + + nk_layout_row_template_end(context); + + _to_start(context, media.begin); + _previus(context, media.previous); + _playback(context, media.reverse, media.pause); + _play(context, media.play, media.pause); + _next(context, media.next); + _to_end(context, media.end); + + get_settings_singleton()->time_ms = MAX_DELAY_MS - nk_slide_int(context, 0, MAX_DELAY_MS - get_settings_singleton()->time_ms, MAX_DELAY_MS, MAX_DELAY_MS / 10); } -void _to_start(struct nk_context * context) { - if (nk_button_label(context, "START")) { +void _to_start(struct nk_context * context, struct nk_image image) { + if (nk_button_image(context, image)) { state_provider(START_VALUE_DS); } } -void _previus(struct nk_context * context) { - if (nk_button_label(context, "PREV")) { +void _previus(struct nk_context * context, struct nk_image image) { + if (nk_button_image(context, image)) { get_player_singleton()->play_state = STOP_MIDDLE_E; state_provider(PREV_VALUE_DS); } } -void _playback(struct nk_context * context) { +void _playback(struct nk_context * context, struct nk_image play, struct nk_image stop) { if (get_player_singleton()->play_state != PLAY_BACKWARDS_E) { - if (nk_button_label(context, "BACK") && get_player_singleton()->play_state != STOP_START_E) { + if (nk_button_image(context, play) && get_player_singleton()->play_state != STOP_START_E) { get_player_singleton()->play_state = PLAY_BACKWARDS_E; } } else { - if (nk_button_label(context, "STOP") && get_player_singleton()->play_state != STOP_START_E) { + if (nk_button_image(context, stop) && get_player_singleton()->play_state != STOP_START_E) { get_player_singleton()->play_state = STOP_MIDDLE_E; } } } -void _play(struct nk_context * context) { +void _play(struct nk_context * context, struct nk_image play, struct nk_image stop) { if (get_player_singleton()->play_state != PLAY_FORWARDS_E) { - if (nk_button_label(context, "FORW") && get_player_singleton()->play_state != STOP_END_E) { + if (nk_button_image(context, play) && get_player_singleton()->play_state != STOP_END_E) { get_player_singleton()->play_state = PLAY_FORWARDS_E; } } else { - if (nk_button_label(context, "STOP") && get_player_singleton()->play_state != STOP_END_E) { + if (nk_button_image(context, stop) && get_player_singleton()->play_state != STOP_END_E) { get_player_singleton()->play_state = STOP_MIDDLE_E; } } } -void _next(struct nk_context * context) { - if (nk_button_label(context, "NEXT")) { +void _next(struct nk_context * context, struct nk_image image) { + if (nk_button_image(context, image)) { get_player_singleton()->play_state = STOP_MIDDLE_E; state_provider(NEXT_VALUE_DS); } } -void _to_end(struct nk_context * context) { - if (nk_button_label(context, "END") && get_player_singleton()->solve_state == SOLVE_FINISHED_E) { +void _to_end(struct nk_context * context, struct nk_image image) { + if (nk_button_image(context, image) && get_player_singleton()->solve_state == SOLVE_FINISHED_E) { state_provider(END_VALUE_DS); } } diff --git a/program/source/gui/interface/solver.c b/program/source/gui/interface/solver.c index 43a61df..9b76e16 100644 --- a/program/source/gui/interface/solver.c +++ b/program/source/gui/interface/solver.c @@ -163,8 +163,8 @@ void _destroy_ds(stack_s * prev, stack_s * next) { read_return = read(pipefd[READ_PIPE_E], &state, sizeof(state_array_s)); expect(-1 != read_return, NO_ACTION, "[ERROR] Read from pipe failed: %s", strerror(errno)); } - expect(0 == close(pipefd[READ_PIPE_E]), NO_ACTION, "[ERROR] Read pipe failed to close with error: %s", strerror(errno)); - expect(0 == close(pipefd[WRITE_PIPE_E]), NO_ACTION, "[ERROR] Write pipe failed to close with error: %s", strerror(errno)); + close(pipefd[READ_PIPE_E]); + close(pipefd[WRITE_PIPE_E]); } void _reset_ds(stack_s * prev, stack_s * next) { diff --git a/program/source/instance/settings.c b/program/source/instance/settings.c index 49240bb..c306fc7 100644 --- a/program/source/instance/settings.c +++ b/program/source/instance/settings.c @@ -7,7 +7,7 @@ Settings * get_settings_singleton(void) { .is_forward_check = false, .is_arc_consistency = false, .is_reduce = false, - .time_ms = 100, + .time_ms = MAX_DELAY_MS / 2, }; return &setup; diff --git a/test/blackbox/CMakeLists.txt b/test/blackbox/CMakeLists.txt index 231ade6..cac6915 100644 --- a/test/blackbox/CMakeLists.txt +++ b/test/blackbox/CMakeLists.txt @@ -26,4 +26,8 @@ target_link_libraries(BLACKBOX program ) -add_test(NAME BLACKBOX_TEST COMMAND BLACKBOX WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}") +add_test( + NAME BLACKBOX_TEST + COMMAND BLACKBOX + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" +)