From 95b77cb696facc30b3138570a7d9e12e5b2591a7 Mon Sep 17 00:00:00 2001 From: Green Sky Date: Tue, 1 Aug 2023 18:25:56 +0200 Subject: [PATCH] add avatar texture handling --- external/solanaceae_contact | 2 +- src/chat_gui4.cpp | 18 +++++++++- src/texture_cache.hpp | 8 +++-- src/tox_avatar_loader.cpp | 72 ++++++++++++++++++++++++++++++++++++- src/tox_avatar_loader.hpp | 5 ++- 5 files changed, 99 insertions(+), 6 deletions(-) diff --git a/external/solanaceae_contact b/external/solanaceae_contact index 65d253a..738d2ab 160000 --- a/external/solanaceae_contact +++ b/external/solanaceae_contact @@ -1 +1 @@ -Subproject commit 65d253afeaf7e39594ecc0a07864a4f4a87086fd +Subproject commit 738d2abe7b4d6088412e56b89f4e26aab1a8bdba diff --git a/src/chat_gui4.cpp b/src/chat_gui4.cpp index b0dc638..626c513 100644 --- a/src/chat_gui4.cpp +++ b/src/chat_gui4.cpp @@ -31,6 +31,18 @@ ChatGui4::ChatGui4( } void ChatGui4::render(void) { + if (!_cr.storage().empty()) { // handle force-reloads for avatars + std::vector to_purge; + _cr.view().each([&to_purge](const Contact3 c) { + to_purge.push_back(c); + }); + _cr.remove(to_purge.cbegin(), to_purge.cend()); + _contact_tc.invalidate(to_purge); + } + // ACTUALLY NOT IF RENDERED, MOVED LOGIC TO ABOVE + // it might unload textures, so it needs to be done before rendering + _contact_tc.update(); + const ImGuiViewport* viewport = ImGui::GetMainViewport(); ImGui::SetNextWindowPos(viewport->WorkPos); ImGui::SetNextWindowSize(viewport->WorkSize); @@ -122,6 +134,11 @@ void ChatGui4::render(void) { if (ImGui::BeginChild("message_log", {0, -100}, false, ImGuiWindowFlags_MenuBar)) { if (ImGui::BeginMenuBar()) { ImGui::Checkbox("show extra info", &_show_chat_extra_info); + if (ImGui::SmallButton("test")) { + _cr.emplace_or_replace(*_selected_contact, "tomato_v1_256.bmp"); + _cr.emplace_or_replace(*_selected_contact); + std::cout << "DEBUG: added AvatarFile comp to contact\n"; + } ImGui::EndMenuBar(); } @@ -276,7 +293,6 @@ void ChatGui4::render(void) { _fss.render(); - _contact_tc.update(); _contact_tc.workLoadQueue(); } diff --git a/src/texture_cache.hpp b/src/texture_cache.hpp index cfcee68..7717d56 100644 --- a/src/texture_cache.hpp +++ b/src/texture_cache.hpp @@ -136,14 +136,18 @@ struct TextureCache { } } + invalidate(to_purge); + + _default_texture.doAnimation(ts_now); + } + + void invalidate(const std::vector& to_purge) { for (const auto& key : to_purge) { for (const auto& tex_id : _cache.at(key).textures) { _tu.destroy(tex_id); } _cache.erase(key); } - - _default_texture.doAnimation(ts_now); } void workLoadQueue(void) { diff --git a/src/tox_avatar_loader.cpp b/src/tox_avatar_loader.cpp index ab6e129..a45bb53 100644 --- a/src/tox_avatar_loader.cpp +++ b/src/tox_avatar_loader.cpp @@ -1,13 +1,23 @@ #include "./tox_avatar_loader.hpp" +#include "./image_loader_sdl_bmp.hpp" + +#include #include #include #include +#include #include #include +ToxAvatarLoader::ToxAvatarLoader(Contact3Registry& cr) : _cr(cr) { + _image_loaders.push_back(std::make_unique()); + //_image_loaders.push_back(std::make_unique()); + //_image_loaders.push_back(std::make_unique()); +} + static float getHue_6bytes(const uint8_t* data) { uint64_t hue_uint = 0x00; for (size_t i = 0; i < 6; i++) { @@ -105,6 +115,66 @@ std::optional ToxAvatarLoader::load(TextureUploaderI& tu, Contact3 return std::nullopt; } + if (_cr.all_of(c)) { + const auto& a_m = _cr.get(c); + + TextureEntry new_entry; + new_entry.timestamp_last_rendered = getNowMS(); + new_entry.current_texture = 0; + + new_entry.width = a_m.width; + new_entry.height = a_m.height; + + const auto n_t = tu.uploadRGBA(a_m.data.data(), a_m.width, a_m.height); + new_entry.textures.push_back(n_t); + new_entry.frame_duration.push_back(250); + + std::cout << "TAL: loaded memory buffer\n"; + + return new_entry; + } + + if (_cr.all_of(c)) { + const auto& a_f = _cr.get(c); + + std::ifstream file(a_f.file_path, std::ios::binary); + if (file.is_open()) { + std::vector tmp_buffer; + while (file.good()) { + auto ch = file.get(); + if (ch == EOF) { + break; + } else { + tmp_buffer.push_back(ch); + } + } + + // try all loaders after another + for (auto& il : _image_loaders) { + auto res = il->loadFromMemoryRGBA(tmp_buffer.data(), tmp_buffer.size()); + if (res.frames.empty() || res.height == 0 || res.width == 0) { + continue; + } + + TextureEntry new_entry; + new_entry.timestamp_last_rendered = getNowMS(); + new_entry.current_texture = 0; + for (const auto& [ms, data] : res.frames) { + const auto n_t = tu.uploadRGBA(data.data(), res.width, res.height); + new_entry.textures.push_back(n_t); + new_entry.frame_duration.push_back(ms); + } + + new_entry.width = res.width; + new_entry.height = res.height; + + std::cout << "TAL: loaded image file " << a_f.file_path << "\n"; + + return new_entry; + } + } + } + if (!_cr.any_of< Contact::Components::ToxFriendPersistent, Contact::Components::ToxGroupPersistent, @@ -133,7 +203,7 @@ std::optional ToxAvatarLoader::load(TextureUploaderI& tu, Contact3 new_entry.width = 5; new_entry.height = 5; - std::cout << "TAL: generateToxIdenticon\n"; + std::cout << "TAL: generated ToxIdenticon\n"; return new_entry; } diff --git a/src/tox_avatar_loader.hpp b/src/tox_avatar_loader.hpp index 08f91d8..41541a7 100644 --- a/src/tox_avatar_loader.hpp +++ b/src/tox_avatar_loader.hpp @@ -2,6 +2,7 @@ #include +#include "./image_loader.hpp" #include "./texture_cache.hpp" #include @@ -9,8 +10,10 @@ class ToxAvatarLoader { Contact3Registry& _cr; + std::vector> _image_loaders; + public: - ToxAvatarLoader(Contact3Registry& cr) : _cr(cr) {} + ToxAvatarLoader(Contact3Registry& cr); std::optional load(TextureUploaderI& tu, Contact3 c); };