diff --git a/src/util/animations.hpp b/src/util/animations.hpp new file mode 100644 index 00000000..c6a9b7bb --- /dev/null +++ b/src/util/animations.hpp @@ -0,0 +1,89 @@ +#pragma once + +#include "file_manager.hpp" +#include "file_manager/file.hpp" +#include "notify.hpp" +#include "thread_pool.hpp" + +namespace big::animations +{ + + inline static std::multimap all_anims; + inline static std::vector all_dicts; + + /* + Built with https://raw.githubusercontent.com/DurtyFree/gta-v-data-dumps/master/animDictsCompact.json in mind + */ + void populate_anim_list(nlohmann::json j) + { + for (const auto& animdict : j) + { + std::string dict = animdict["DictionaryName"]; + + auto it = std::find(all_dicts.begin(), all_dicts.end(), dict); + + if (it == all_dicts.end()) + all_dicts.push_back(dict); + + for (const auto& anim : animdict["Animations"]) + { + all_anims.emplace(dict, anim); + } + } + } + + inline bool has_anim_list_been_populated() + { + return all_anims.size() > 0; + } + + inline int anim_dict_count() + { + return all_dicts.size(); + } + + inline int total_anim_count() + { + return all_anims.size(); + } + + inline void fetch_all_anims() + { + if (has_anim_list_been_populated()) + LOG(WARNING) << "Anim list already contained data, overwriting..."; + + all_anims.clear(); + all_dicts.clear(); + + if (!std::filesystem::exists(g_file_manager->get_project_file("animDictsCompact.json").get_path())) + { + LOG(INFO) << "Animations file is not in directory. https://raw.githubusercontent.com/DurtyFree/gta-v-data-dumps/master/animDictsCompact.json"; + g_notification_service->push_warning("Animations", "Please download the appropriate animations json and put it in the mod directory."); + return; + } + + auto path = g_file_manager->get_project_file("animDictsCompact.json").get_path(); + + try + { + g_thread_pool->push([=] { + std::ifstream file(path); + + if (!file.is_open()) + return; + + nlohmann::json j; + + file >> j; + populate_anim_list(j); + }); + + if (has_anim_list_been_populated()) + LOG(INFO) << "Succesfully fetched " << anim_dict_count() << " dictionaries with a total of " << total_anim_count() << " animations."; + } + catch (std::exception e) + { + LOG(WARNING) << "Failed fetching all anims: " << e.what(); + } + } +} \ No newline at end of file diff --git a/src/views/debug/view_debug.cpp b/src/views/debug/view_debug.cpp index d07c7f0d..92e47b77 100644 --- a/src/views/debug/view_debug.cpp +++ b/src/views/debug/view_debug.cpp @@ -19,6 +19,7 @@ namespace big script_events(); scripts(); threads(); + animations(); ImGui::EndTabBar(); } ImGui::End(); diff --git a/src/views/debug/view_debug.hpp b/src/views/debug/view_debug.hpp index f6335c24..1afce488 100644 --- a/src/views/debug/view_debug.hpp +++ b/src/views/debug/view_debug.hpp @@ -9,6 +9,7 @@ namespace big::debug extern void script_events(); extern void scripts(); extern void threads(); + extern void animations(); extern void main(); } \ No newline at end of file diff --git a/src/views/debug/view_debug_animations.cpp b/src/views/debug/view_debug_animations.cpp new file mode 100644 index 00000000..759169eb --- /dev/null +++ b/src/views/debug/view_debug_animations.cpp @@ -0,0 +1,76 @@ +#include "gui/components/components.hpp" +#include "util/animations.hpp" +#include "util/ped.hpp" +#include "view_debug.hpp" + +namespace big +{ + void debug::animations() + { + if (ImGui::BeginTabItem("Animations")) + { + static std::string current_dict, current_anim; + static std::vector selected_dict_anim_list{}; + + static auto reload_anim_list = []() -> void { + selected_dict_anim_list.clear(); + auto range = animations::all_anims.equal_range(current_dict); + for (auto it = range.first; it != range.second; ++it) + { + selected_dict_anim_list.push_back(it->second); + } + }; + + ImGui::Text("There are %d dictionaries with %d animations in memory", animations::anim_dict_count(), animations::total_anim_count()); + + components::button("Fetch All Anims", [] { + animations::fetch_all_anims(); + }); + + ImGui::SetNextItemWidth(400); + components::input_text_with_hint("", "Dictionary", ¤t_dict); + + if (animations::has_anim_list_been_populated() && ImGui::ListBoxHeader("##dictionaries", ImVec2(400, 200))) + { + for (auto& entry : animations::all_dicts) + { + std::string entry_lowercase = entry; + std::string search_lowercase = current_dict; + std::transform(entry.begin(), entry.end(), entry.begin(), ::tolower); + std::transform(current_dict.begin(), current_dict.end(), current_dict.begin(), ::tolower); + if (entry.find(search_lowercase) != std::string::npos && ImGui::Selectable(entry.data())) + { + current_dict = entry; + reload_anim_list(); + } + } + + ImGui::ListBoxFooter(); + } + + if (selected_dict_anim_list.size() > 0 && ImGui::ListBoxHeader("##animations", ImVec2(400, 200))) + { + for (auto& entry : selected_dict_anim_list) + { + if (ImGui::Selectable(entry.data(), entry == current_anim)) + { + current_anim = entry; + + g_fiber_pool->queue_job([=] { + TASK::CLEAR_PED_TASKS_IMMEDIATELY(self::ped); + ped::ped_play_animation(self::ped, current_dict, current_anim, 4.f, -4.f, -1, 0, 0, false); + }); + } + } + + ImGui::ListBoxFooter(); + } + + components::button("Stop", [] { + TASK::CLEAR_PED_TASKS(self::ped); + }); + + ImGui::EndTabItem(); + } + } +} \ No newline at end of file