diff --git a/.DS_Store b/.DS_Store index df550cc..6f395db 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/include/common.h b/include/common.h index 2c732ff..e4f1207 100644 --- a/include/common.h +++ b/include/common.h @@ -25,13 +25,15 @@ typedef int (*Error_Handler)(enum pksav_error, const char *); -enum single_player_menu_types { +enum single_player_menu_types +{ SINGLE_PLAYER_MENU_TYPE_EVOLVE, SINGLE_PLAYER_MENU_TYPE_BILLS_PC, SINGLE_PLAYER_MENU_TYPE_EXIT }; -union PokemonPartyData { +union PokemonPartyData +{ struct pksav_gen1_pokemon_party gen1_pokemon_party; struct pksav_gen2_pokemon_party gen2_pokemon_party; }; @@ -49,7 +51,8 @@ struct TrainerSelection int trainer_index; }; -typedef enum { +typedef enum +{ SCREEN_ERROR = -1, SCREEN_FILE_SELECT, SCREEN_TRADE, @@ -64,11 +67,12 @@ typedef enum { SCREEN_LEGAL } GameScreen; -struct save_file_data { +struct save_file_data +{ // current saves file directory string char save_dir[MAX_FILE_PATH_CHAR]; // array of saves file paths in the current saves file directory - char *saves_file_path[MAX_FILE_PATH_COUNT]; + char saves_file_path[MAX_FILE_PATH_COUNT][MAX_FILE_PATH_CHAR]; int num_saves; }; @@ -86,7 +90,8 @@ typedef union struct pksav_gen2_save gen2_save; } SaveGeneration; -typedef struct { +typedef struct +{ SaveGenerationType save_generation_type; SaveGeneration save; } PokemonSave; @@ -108,36 +113,39 @@ enum E_LOG_MESSAGE_TYPE E_LOG_MESSAGE_TYPE_INFO }; -enum textures { - T_NONE = -1, - T_EVOLVE, - T_LOGO, - T_QUIT, - T_SETTINGS, - T_TRADE, - T_CONSOLE_0, - T_CONSOLE_1, - T_CONSOLE_2, - T_CONSOLE_3, - T_CONSOLE_4, - T_CONSOLE_5, - T_CONSOLE_6, - T_CONSOLE_7, - T_CONSOLE_8, - T_CONSOLE_9, - T_POKEBALL_0, - T_POKEBALL_1, - T_POKEBALL_2, - T_POKEBALL_3, - T_COUNT - }; - -enum file_op_results { - FILE_OP_SUCCESS = 0, - FILE_OP_FAILURE +enum textures +{ + T_NONE = -1, + T_EVOLVE, + T_LOGO, + T_QUIT, + T_SETTINGS, + T_TRADE, + T_CONSOLE_0, + T_CONSOLE_1, + T_CONSOLE_2, + T_CONSOLE_3, + T_CONSOLE_4, + T_CONSOLE_5, + T_CONSOLE_6, + T_CONSOLE_7, + T_CONSOLE_8, + T_CONSOLE_9, + T_POKEBALL_0, + T_POKEBALL_1, + T_POKEBALL_2, + T_POKEBALL_3, + T_COUNT +}; + +enum file_op_results +{ + FILE_OP_FAILURE = 0, + FILE_OP_SUCCESS = 1 }; -typedef enum { +typedef enum +{ error_none, error_swap_pkmn, error_update_save, diff --git a/include/components.h b/include/components.h index 2e601ac..b774e5d 100644 --- a/include/components.h +++ b/include/components.h @@ -20,6 +20,7 @@ void draw_confirmation_modal(const char *header_text, const char *body_text, con void draw_trainer_info(struct trainer_info *trainer, int x, int y, struct TrainerSelection trainerSelection[2], bool is_same_generation, bool *is_valid_trade); void reset_details_panel(void); void draw_save_file_container(PokemonSave *pkmn_save, char *save_name, Rectangle container_rec, bool is_selected); +void draw_drag_drop_container(Rectangle container_rec); void draw_corrupted_save(const char *save_name, const int y_offset, const int index, const int corrupted_count); void draw_pokeball_scroll(float scroll_position, float transparency); void draw_pokeball(int pos_x, int pos_y, int scale); diff --git a/src/components/DragDropContainer.c b/src/components/DragDropContainer.c new file mode 100644 index 0000000..b668491 --- /dev/null +++ b/src/components/DragDropContainer.c @@ -0,0 +1,14 @@ +#include "raylibhelper.h" + +void draw_drag_drop_container(Rectangle container_rec) +{ + DrawRectangleRec(container_rec, (Color){62, 60, 153, 125}); + + // draw border + DrawRectangleLinesEx((Rectangle){container_rec.x - 4, container_rec.y - 4, container_rec.width + 8, container_rec.height + 8}, 1, BLACK); + DrawRectangleLinesEx((Rectangle){container_rec.x - 3, container_rec.y - 3, container_rec.width + 6, container_rec.height + 6}, 3, (Color){255, 255, 255, 125}); + DrawRectangleLinesEx((Rectangle){container_rec.x, container_rec.y, container_rec.width, container_rec.height}, 1, BLACK); + + // draw text centered horizontally and vertically + shadow_text("Drag and Drop save files here", container_rec.x + container_rec.width / 2 - MeasureText("Drag and Drop save files here", 20) / 2, container_rec.y + container_rec.height / 2 - 20 / 2, 20, (Color){255, 255, 255, 200}); +} diff --git a/src/filehelper.c b/src/filehelper.c index 432af6c..ca0f2f4 100644 --- a/src/filehelper.c +++ b/src/filehelper.c @@ -51,15 +51,11 @@ int get_save_files(struct save_file_data *save_data) // Combine the base path and file name char full_path[MAX_FILE_PATH_CHAR]; sprintf(full_path, "%s/%s", save_dir, find_file_data.cFileName); - printf("Found file: %s\n", full_path); - save_data->saves_file_path[num_saves] = malloc(strlen(full_path) + 1); strcpy(save_data->saves_file_path[num_saves], full_path); - printf("Saved file: %s\n", save_data->saves_file_path[num_saves]); num_saves++; } while (FindNextFile(hFind, &find_file_data) != 0); FindClose(hFind); save_data->num_saves = num_saves; - printf("num_saves from load: %d\n", save_data->num_saves); } return 0; @@ -140,7 +136,6 @@ void create_default_config(void) LPCSTR ini = config_path; WritePrivateProfileStringA("app", "SAVE_FILE_DIR", saves_dir, ini); - WritePrivateProfileStringA("app", "DISABLE_RANDOM_IVS_ON_TRADE", "false", ini); } struct config_data read_key_from_config(void) { @@ -160,13 +155,8 @@ struct config_data read_key_from_config(void) char save_file_str[MAX_FILE_PATH_CHAR]; GetPrivateProfileString("app", "SAVE_FILE_DIR", 0, save_file_str, MAX_FILE_PATH_CHAR, ini); - char disable_random_ivs_on_trade[MAX_FILE_PATH_CHAR]; - GetPrivateProfileString("app", "DISABLE_RANDOM_IVS_ON_TRADE", 0, disable_random_ivs_on_trade, MAX_FILE_PATH_CHAR, ini); - - return (struct config_data){ - .save_file_dir = save_file_str, - .disable_random_ivs_on_trade = disable_random_ivs_on_trade, + .save_file_dir = save_file_str }; } void write_to_log(const char *msg, const uint8_t message_type) @@ -371,7 +361,7 @@ int get_save_files(struct save_file_data *save_data) absolute_path = realpath(full_path, NULL); if (absolute_path) { - save_data->saves_file_path[num_saves] = absolute_path; + strcpy(save_data->saves_file_path[num_saves],absolute_path); num_saves++; } } @@ -394,7 +384,7 @@ int write_key_to_config(const char *key, const char *value) if (file == NULL) { perror("Error opening INI file"); - return 1; + return FILE_OP_FAILURE; } // Create a temporary file to store the modified contents. @@ -403,7 +393,7 @@ int write_key_to_config(const char *key, const char *value) { perror("Error creating temporary file"); fclose(file); - return 1; + return FILE_OP_FAILURE; } char line[1024]; @@ -442,7 +432,7 @@ int write_key_to_config(const char *key, const char *value) { perror("Error reopening INI file"); fclose(temp_file); - return 1; + return FILE_OP_FAILURE; } while (fgets(line, sizeof(line), temp_file) != NULL) @@ -456,7 +446,7 @@ int write_key_to_config(const char *key, const char *value) // Close the INI file. fclose(file); - return 0; + return FILE_OP_SUCCESS; } void create_default_config(bool overwrite) diff --git a/src/pksavfilehelper.c b/src/pksavfilehelper.c index ee3e2f4..4018ce1 100644 --- a/src/pksavfilehelper.c +++ b/src/pksavfilehelper.c @@ -5,7 +5,7 @@ * @param path the path to the save file * @param save_generation_type a pointer to a SaveGenerationType to store the save generation type * @return an enum pksav_error -*/ + */ enum pksav_error detect_savefile_generation(const char *path, SaveGenerationType *save_generation_type) { enum pksav_error err = PKSAV_ERROR_NONE; @@ -39,7 +39,7 @@ enum pksav_error detect_savefile_generation(const char *path, SaveGenerationType * @brief loads a save file from a path in the buffer * @param path the path to the save file * @return a PokemonSave struct -*/ + */ void load_savefile_from_path(const char *path, PokemonSave *pkmn_save) { enum pksav_error err = PKSAV_ERROR_NONE; @@ -96,7 +96,7 @@ void load_savefile_from_path(const char *path, PokemonSave *pkmn_save) * @brief saves the save buffer to a path * @param pkmn_save a pointer to a PokemonSave struct save buffer * @param path the path to the save file -*/ + */ pksavhelper_error save_savefile_to_path(PokemonSave *pkmn_save, char *path) { enum pksav_error err = PKSAV_ERROR_NONE; @@ -136,8 +136,15 @@ void load_display_files(const struct save_file_data *save_file_data, PokemonSave if (pkmn_saves[i].save_generation_type == SAVE_GENERATION_NONE) { load_savefile_from_path(save_file_data->saves_file_path[i], &pkmn_saves[i]); - allocated_saves++; - save_file_size += pkmn_saves[i].save_generation_type == SAVE_GENERATION_1 ? sizeof(struct pksav_gen1_save) : sizeof(struct pksav_gen2_save); + if (pkmn_saves[i].save_generation_type != SAVE_GENERATION_NONE) + { + allocated_saves++; + save_file_size += pkmn_saves[i].save_generation_type == SAVE_GENERATION_1 ? sizeof(struct pksav_gen1_save) : sizeof(struct pksav_gen2_save); + } + else + { + puts("PokeromTrader: Not a pokemon save file"); + } } } if (allocated_saves > 0) @@ -154,7 +161,7 @@ void free_pkmn_saves(PokemonSave *pkmn_saves, uint8_t *save_file_count) return; } uint8_t count = 0; - printf("PokeromTrader: %u save files had been allocated", *save_file_count); + printf("PokeromTrader: %u save files had been allocated\n", *save_file_count); for (int i = 0; i < *save_file_count; i++) { switch (pkmn_saves[i].save_generation_type) @@ -185,9 +192,9 @@ void free_pkmn_saves(PokemonSave *pkmn_saves, uint8_t *save_file_count) *save_file_count -= count; - printf(" / %d save files deallocated\n", count); + printf("%d save files deallocated\n", count); - if (*save_file_count != 0) + if (*save_file_count != 0) { printf("PokeromTrader: %d save files were not deallocated\n", *save_file_count); } diff --git a/src/raylibhelper.c b/src/raylibhelper.c index 9f8a856..03c6e0d 100644 --- a/src/raylibhelper.c +++ b/src/raylibhelper.c @@ -163,7 +163,10 @@ void draw_no_save_files(char *save_path) { shadow_text("No save files found in save folder", 190, 200, 20, WHITE); } - shadow_text(TextFormat("%s", save_path), SCREEN_CENTER(save_path, 20).x, 275, 20, WHITE); + shadow_text(TextFormat("%s", save_path), SCREEN_CENTER(save_path, 20).x, 230, 20, WHITE); + + char *text = "Add save files to the save folder or drag and drop save files here!"; + shadow_text(text, SCREEN_CENTER(text, 20).x, 300, 20, WHITE); } void draw_top_banner(const char *text, const int *banner_position_offset) diff --git a/src/screens/ChangeDirScreen.c b/src/screens/ChangeDirScreen.c index 97e0778..82c32e2 100644 --- a/src/screens/ChangeDirScreen.c +++ b/src/screens/ChangeDirScreen.c @@ -62,6 +62,25 @@ void draw_change_dir(struct save_file_data *save_file_data, GameScreen *current_ has_reset_config = false; } + if (IsFileDropped()) + { + FilePathList dropped_files = LoadDroppedFiles(); + if (dropped_files.count > 0) + { + if (!IsPathFile(dropped_files.paths[0])) + { + strcpy(input_text, dropped_files.paths[0]); + } + else + { + strcpy(input_text, GetDirectoryPath(dropped_files.paths[0])); + } + + } + + UnloadDroppedFiles(dropped_files); + } + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { // Check if the mouse is clicked within the input box @@ -107,6 +126,7 @@ void draw_change_dir(struct save_file_data *save_file_data, GameScreen *current_ DrawTextureEx(*settings_texture, (Vector2){50, 35}, 0, 1, WHITE); DrawText("Specify folder name containing saves", 50, SCREEN_HEIGHT / 2 - 50, 25, BLACK); + DrawText("or drag and drop a save file/folder to get the folder path", 50, SCREEN_HEIGHT / 2 - 20, 15, BLACK); // Draw the input box DrawRectangleRec(input_box_rec, WHITE); @@ -208,7 +228,6 @@ void draw_change_dir(struct save_file_data *save_file_data, GameScreen *current_ { strcpy((char *)save_file_data->save_dir, input_text); save_file_data->num_saves = 0; - *save_file_data->saves_file_path = NULL; *current_screen = SCREEN_SETTINGS; has_shown_placeholder = false; } diff --git a/src/screens/FileSelectScreen.c b/src/screens/FileSelectScreen.c index fb98733..66762b1 100644 --- a/src/screens/FileSelectScreen.c +++ b/src/screens/FileSelectScreen.c @@ -49,6 +49,30 @@ void draw_file_select(struct save_file_data *save_file_data, char *player1_save_ draw_background_grid(); + if (IsFileDropped()) + { + FilePathList dropped_files = LoadDroppedFiles(); + for (size_t i = 0; i < dropped_files.count; i++) + { + if (save_file_data->num_saves < MAX_FILE_PATH_COUNT) + { + // swap \\ with / in doprped file paths + for (size_t j = 0; j < strlen(dropped_files.paths[i]); j++) + { + if (dropped_files.paths[i][j] == '\\') + { + dropped_files.paths[i][j] = '/'; + } + } + + strcpy(save_file_data->saves_file_path[save_file_data->num_saves], dropped_files.paths[i]); + printf("Dropped file: %s\n", dropped_files.paths[i]); + save_file_data->num_saves++; + } + } + UnloadDroppedFiles(dropped_files); + } + if (save_file_data->num_saves == 0) { draw_no_save_files(save_file_data->save_dir); @@ -65,13 +89,14 @@ void draw_file_select(struct save_file_data *save_file_data, char *player1_save_ for (int i = 0; i < save_file_data->num_saves; i++) { bool is_corrupted = pkmn_saves[i].save_generation_type == SAVE_GENERATION_CORRUPTED; + // bool is_corrupted = false; const Rectangle save_file_rec = (Rectangle){SCREEN_WIDTH / 2 - (SCREEN_WIDTH - 50) / 2, y_offset + (93 * i) - (60 * corrupted_count), SCREEN_WIDTH - 50, 80}; // Update selected save files index update_selected_indexes_with_selection(selected_saves_index, &mouses_down_index, &is_moving_scroll); // Extract save file name from path - char *save_name = strrchr(save_file_data->saves_file_path[i], '/') + 1; + char *save_name = strrchr(save_file_data->saves_file_path[i], '/') + 1; // this crashes on windows because of / // Draw save file container if (is_corrupted) @@ -99,8 +124,10 @@ void draw_file_select(struct save_file_data *save_file_data, char *player1_save_ } } } + // Draw drag and drop container + draw_drag_drop_container((Rectangle){SCREEN_WIDTH / 2 - (SCREEN_WIDTH - 50) / 2, y_offset + (93 * save_file_data->num_saves) - (60 * corrupted_count), SCREEN_WIDTH - 50, 80}); - handle_list_scroll(&y_offset, save_file_data->num_saves, corrupted_count, &mouses_down_index, &is_moving_scroll, &banner_position_offset); + handle_list_scroll(&y_offset, save_file_data->num_saves + 1, corrupted_count, &mouses_down_index, &is_moving_scroll, &banner_position_offset); } // Top Banner diff --git a/src/screens/SingleFileSelectScreen.c b/src/screens/SingleFileSelectScreen.c index 9800ace..03f0d2b 100644 --- a/src/screens/SingleFileSelectScreen.c +++ b/src/screens/SingleFileSelectScreen.c @@ -33,6 +33,20 @@ void draw_file_select_single(struct save_file_data *save_file_data, PokemonSave ClearBackground(RED); draw_background_grid(); + if (IsFileDropped()) + { + FilePathList dropped_files = LoadDroppedFiles(); + for (size_t i = 0; i < dropped_files.count; i++) + { + if (save_file_data->num_saves < MAX_FILE_PATH_COUNT) + { + strcpy(save_file_data->saves_file_path[save_file_data->num_saves], dropped_files.paths[i]); + save_file_data->num_saves++; + } + } + UnloadDroppedFiles(dropped_files); + } + if (save_file_data->num_saves == 0) { draw_no_save_files(save_file_data->save_dir); @@ -46,8 +60,14 @@ void draw_file_select_single(struct save_file_data *save_file_data, PokemonSave load_display_files(save_file_data, pkmn_saves, &save_file_count); // Update and draw save files - for (int i = 0; i < save_file_data->num_saves; i++) + for (int i = 0; i < save_file_data->num_saves + 1; i++) { + if (i == save_file_data->num_saves) + { + // Draw drag and drop container + draw_drag_drop_container((Rectangle){SCREEN_WIDTH / 2 - (SCREEN_WIDTH - 50) / 2, y_offset + (93 * i) - (60 * corrupted_count), SCREEN_WIDTH - 50, 80}); + break; + } bool is_corrupted = pkmn_saves[i].save_generation_type == SAVE_GENERATION_CORRUPTED; const Rectangle save_file_rec = (Rectangle){SCREEN_WIDTH / 2 - (SCREEN_WIDTH - 50) / 2, y_offset + (93 * i) - (60 * corrupted_count), SCREEN_WIDTH - 50, 80};