Compare commits

..

12 Commits

Author SHA1 Message Date
Green Sky
2dbce14e5e make texture cache scale down images on load to the requested size
Some checks failed
ContinuousDelivery / linux-ubuntu (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, ) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, asan) (push) Has been cancelled
ContinuousIntegration / on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousIntegration / macos (push) Has been cancelled
ContinuousIntegration / windows (push) Has been cancelled
ContinuousDelivery / dumpsyms (push) Has been cancelled
ContinuousDelivery / release (push) Has been cancelled
2025-12-04 15:56:39 +01:00
Green Sky
997e2517a3 fix crop getting ignored when not scaling (oops)
Some checks failed
ContinuousDelivery / linux-ubuntu (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, ) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, asan) (push) Has been cancelled
ContinuousIntegration / on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousIntegration / macos (push) Has been cancelled
ContinuousIntegration / windows (push) Has been cancelled
ContinuousDelivery / dumpsyms (push) Has been cancelled
ContinuousDelivery / release (push) Has been cancelled
2025-11-23 14:36:04 +01:00
Green Sky
f4350b5d70 wording
Some checks failed
ContinuousDelivery / linux-ubuntu (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, ) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, asan) (push) Has been cancelled
ContinuousDelivery / dumpsyms (push) Has been cancelled
ContinuousDelivery / release (push) Has been cancelled
ContinuousIntegration / on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousIntegration / macos (push) Has been cancelled
ContinuousIntegration / windows (push) Has been cancelled
2025-11-22 20:25:57 +01:00
Green Sky
77c36476a6 rename connection state to what it is and expose more self node info
Some checks failed
ContinuousDelivery / linux-ubuntu (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, ) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, asan) (push) Has been cancelled
ContinuousDelivery / dumpsyms (push) Has been cancelled
ContinuousDelivery / release (push) Has been cancelled
ContinuousIntegration / on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousIntegration / macos (push) Has been cancelled
ContinuousIntegration / windows (push) Has been cancelled
2025-11-22 20:05:36 +01:00
Green Sky
1481b3ec66 add ui for adding a dht node/tcp relay
Some checks failed
ContinuousDelivery / linux-ubuntu (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, ) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, asan) (push) Has been cancelled
ContinuousDelivery / dumpsyms (push) Has been cancelled
ContinuousDelivery / release (push) Has been cancelled
ContinuousIntegration / on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousIntegration / macos (push) Has been cancelled
ContinuousIntegration / windows (push) Has been cancelled
slightly wip
2025-11-22 16:00:47 +01:00
Green Sky
9959932267 no it did not
Some checks failed
ContinuousDelivery / linux-ubuntu (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, ) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, asan) (push) Has been cancelled
ContinuousIntegration / on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousIntegration / macos (push) Has been cancelled
ContinuousIntegration / windows (push) Has been cancelled
ContinuousDelivery / dumpsyms (push) Has been cancelled
ContinuousDelivery / release (push) Has been cancelled
2025-11-18 14:49:52 +01:00
Green Sky
2d536c3597 add shift+g to jump to bottom of chat log
Some checks failed
ContinuousDelivery / linux-ubuntu (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, ) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, asan) (push) Has been cancelled
ContinuousIntegration / on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousIntegration / macos (push) Has been cancelled
ContinuousIntegration / windows (push) Has been cancelled
ContinuousDelivery / dumpsyms (push) Has been cancelled
ContinuousDelivery / release (push) Has been cancelled
2025-11-15 11:27:51 +01:00
Green Sky
7858474d35 switch to wip version number 2025-11-11 20:23:26 +01:00
Green Sky
fe52d7cb12 release v0.3.2
Some checks failed
ContinuousDelivery / linux-ubuntu (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, ) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, asan) (push) Has been cancelled
ContinuousIntegration / on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousIntegration / macos (push) Has been cancelled
ContinuousIntegration / windows (push) Has been cancelled
ContinuousDelivery / dumpsyms (push) Has been cancelled
ContinuousDelivery / release (push) Has been cancelled
2025-11-09 16:38:18 +01:00
Green Sky
571656c64f add quick half and double scale buttons
Some checks failed
ContinuousDelivery / linux-ubuntu (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, ) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, asan) (push) Has been cancelled
ContinuousIntegration / on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousIntegration / macos (push) Has been cancelled
ContinuousIntegration / windows (push) Has been cancelled
ContinuousDelivery / dumpsyms (push) Has been cancelled
ContinuousDelivery / release (push) Has been cancelled
2025-11-06 11:20:12 +01:00
Green Sky
1547999ec0 add image scaling to send image popup
Some checks failed
ContinuousDelivery / linux-ubuntu (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, ) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, asan) (push) Has been cancelled
ContinuousDelivery / dumpsyms (push) Has been cancelled
ContinuousDelivery / release (push) Has been cancelled
ContinuousIntegration / on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousIntegration / macos (push) Has been cancelled
ContinuousIntegration / windows (push) Has been cancelled
2025-11-05 18:53:07 +01:00
Green Sky
e8a15a58dd add image scaler (box sampling) 2025-11-05 00:01:42 +01:00
22 changed files with 489 additions and 67 deletions

View File

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.14...3.24 FATAL_ERROR)
# cmake setup begin # cmake setup begin
project(tomato project(tomato
VERSION 0.3.1 VERSION 0.3.3
HOMEPAGE_URL https://github.com/Green-Sky/tomato HOMEPAGE_URL https://github.com/Green-Sky/tomato
) )

View File

@@ -53,6 +53,8 @@ target_sources(tomato PUBLIC
./image_loader_qoi.cpp ./image_loader_qoi.cpp
./image_loader_sdl_image.hpp ./image_loader_sdl_image.hpp
./image_loader_sdl_image.cpp ./image_loader_sdl_image.cpp
./image_scaler.hpp
./image_scaler.cpp
./texture_uploader.hpp ./texture_uploader.hpp
./sdlrenderer_texture_uploader.hpp ./sdlrenderer_texture_uploader.hpp

View File

@@ -65,7 +65,7 @@ std::optional<TextureEntry> BitsetImageLoader::haveToTexture(TextureUploaderI& t
BitsetImageLoader::BitsetImageLoader(void) { BitsetImageLoader::BitsetImageLoader(void) {
} }
TextureLoaderResult BitsetImageLoader::load(TextureUploaderI& tu, ObjectHandle o) { TextureLoaderResult BitsetImageLoader::load(TextureUploaderI& tu, ObjectHandle o, uint32_t w, uint32_t h) {
if (!static_cast<bool>(o)) { if (!static_cast<bool>(o)) {
std::cerr << "BIL error: trying to load invalid object\n"; std::cerr << "BIL error: trying to load invalid object\n";
return {}; return {};

View File

@@ -34,7 +34,7 @@ class BitsetImageLoader {
public: public:
BitsetImageLoader(void); BitsetImageLoader(void);
TextureLoaderResult load(TextureUploaderI& tu, ObjectHandle o); TextureLoaderResult load(TextureUploaderI& tu, ObjectHandle o, uint32_t w, uint32_t h);
std::optional<TextureEntry> load(TextureUploaderI& tu, ObjectContactSub ocs); std::optional<TextureEntry> load(TextureUploaderI& tu, ObjectContactSub ocs);
}; };

View File

@@ -41,8 +41,12 @@ void renderAvatar(
} }
} }
// TODO: per display?
// TODO: do we really need this? test dpi scaling
const auto [g_scale_x, g_scyle_y] = ImGui::GetIO().DisplayFramebufferScale;
// avatar // avatar
const auto [id, width, height] = contact_tc.get(c); const auto [id, width, height] = contact_tc.get(c, box.x*g_scale_x, box.y*g_scyle_y);
ImGui::Image( ImGui::Image(
id, id,
box, box,

View File

@@ -14,6 +14,8 @@ void ImageViewerPopup::view(Message3Handle m) {
} }
_m = m; _m = m;
_width = 0;
_height = 0;
_open_popup = true; _open_popup = true;
} }
@@ -35,10 +37,13 @@ void ImageViewerPopup::render(float) {
ImGui::SliderFloat("scale", &_scale, 0.05f, 2.f); ImGui::SliderFloat("scale", &_scale, 0.05f, 2.f);
auto [id, img_width, img_height] = _mtc.get(_m); auto [id, img_width, img_height] = _mtc.get(_m, _width, _height);
img_width = std::max<int32_t>(5, _scale * img_width); img_width = std::max<uint32_t>(5, _scale * img_width);
img_height = std::max<int32_t>(5, _scale * img_height); img_height = std::max<uint32_t>(5, _scale * img_height);
_width = img_width;
_height = img_height;
ImGui::Image( ImGui::Image(
id, id,

View File

@@ -12,6 +12,9 @@ struct ImageViewerPopup {
Message3Handle _m{}; Message3Handle _m{};
float _scale {1.f}; float _scale {1.f};
// keep track of full size from last frame
uint32_t _width {0};
uint32_t _height {0};
bool _open_popup {false}; bool _open_popup {false};

View File

@@ -13,7 +13,9 @@
#include <imgui.h> #include <imgui.h>
#include <cstdint>
#include <cmath> #include <cmath>
#include <iostream>
SendImagePopup::SendImagePopup(TextureUploaderI& tu) : _tu(tu) { SendImagePopup::SendImagePopup(TextureUploaderI& tu) : _tu(tu) {
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>()); _image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
@@ -245,7 +247,7 @@ void SendImagePopup::render(float time_delta) {
- ( - (
ImGui::GetWindowContentRegionMin().y ImGui::GetWindowContentRegionMin().y
+ TEXT_BASE_HEIGHT*(2-1) // row of buttons (-1 bc fh inclues fontsize) + TEXT_BASE_HEIGHT*(2-1) // row of buttons (-1 bc fh inclues fontsize)
+ ImGui::GetFrameHeightWithSpacing()*4 + ImGui::GetFrameHeightWithSpacing()*6
) )
; ;
if (height > max_height) { if (height > max_height) {
@@ -340,8 +342,7 @@ void SendImagePopup::render(float time_delta) {
{ // 4 lines delimiting the crop result { // 4 lines delimiting the crop result
ImU32 line_color = 0xffffffff; ImU32 line_color = 0xffffffff;
{ // calc color { // calc color
auto rgb = [](float x) -> ImVec4 { static constexpr auto f = [](float x) {
auto f = [](float x) {
while (x < 0.f) { while (x < 0.f) {
x += 1.f; x += 1.f;
} }
@@ -356,7 +357,7 @@ void SendImagePopup::render(float time_delta) {
return 0.f; return 0.f;
} }
}; };
auto rgb = [](float x) -> ImVec4 {
float red = f(x); float red = f(x);
float green = f(x - (1.f/3)); float green = f(x - (1.f/3));
float blue = f(x - (2.f/3)); float blue = f(x - (2.f/3));
@@ -434,7 +435,7 @@ void SendImagePopup::render(float time_delta) {
} }
} }
const bool cropped = crop_rect.x != 0 || crop_rect.y != 0 || crop_rect.w != original_image.width || crop_rect.h != original_image.height; const bool cropped = crop_rect.x != 0 || crop_rect.y != 0 || crop_rect.w != int64_t(original_image.width) || crop_rect.h != int64_t(original_image.height);
if (cropping) { if (cropping) {
if (ImGui::Button("done")) { if (ImGui::Button("done")) {
cropping = false; cropping = false;
@@ -445,7 +446,7 @@ void SendImagePopup::render(float time_delta) {
} }
} }
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("reset")) { if (ImGui::Button("reset##crop")) {
crop_rect.x = 0; crop_rect.x = 0;
crop_rect.y = 0; crop_rect.y = 0;
crop_rect.w = original_image.width; crop_rect.w = original_image.width;
@@ -455,6 +456,44 @@ void SendImagePopup::render(float time_delta) {
ImGui::SameLine(); ImGui::SameLine();
ImGui::Text("x:%d y:%d w:%d h:%d", crop_rect.x, crop_rect.y, crop_rect.w, crop_rect.h); ImGui::Text("x:%d y:%d w:%d h:%d", crop_rect.x, crop_rect.y, crop_rect.w, crop_rect.h);
ImGui::TextUnformatted("scale");
ImGui::SameLine();
if (ImGui::Button("reset##scale")) {
scale_x = 1.f;
scale_y = 1.f;
}
ImGui::SameLine();
ImGui::SetNextItemWidth(TEXT_BASE_HEIGHT*3);
if (ImGui::DragFloat("##scale x", &scale_x, 0.001f, 0.001f, 100.f) && scale_tie) {
scale_y = scale_x;
}
ImGui::SameLine();
ImGui::TextUnformatted("X");
ImGui::SameLine();
ImGui::SetNextItemWidth(TEXT_BASE_HEIGHT*3);
if (ImGui::DragFloat("##scale y", &scale_y, 0.001f, 0.001f, 100.f) && scale_tie) {
scale_x = scale_y;
}
ImGui::SameLine();
if (ImGui::Button("/2##scale")) {
scale_x *= 0.5f;
scale_y *= 0.5f;
}
ImGui::SameLine();
if (ImGui::Button("*2##scale")) {
scale_x *= 2.f;
scale_y *= 2.f;
}
ImGui::SameLine();
ImGui::Checkbox("tie", &scale_tie);
if (scale_x <= 0.f) { scale_x = 0.001f; }
if (scale_y <= 0.f) { scale_y = 0.001f; }
if (scale_x > 100.f) { scale_x = 100.f; }
if (scale_y > 100.f) { scale_y = 100.f; }
ImGui::Text("final size -> w:%d h:%d", (int)std::ceil(crop_rect.w*scale_x), (int)std::ceil(crop_rect.h*scale_y));
bool recalc_size = false; bool recalc_size = false;
if (cropped) { if (cropped) {
if (!compress) { if (!compress) {
@@ -463,6 +502,13 @@ void SendImagePopup::render(float time_delta) {
} }
compress = true; compress = true;
} }
if (scale_x != 1.f || scale_y != 1.f) {
if (!compress) {
// looks like a change
recalc_size = true;
}
compress = true;
}
recalc_size |= ImGui::Checkbox("compress", &compress); recalc_size |= ImGui::Checkbox("compress", &compress);
if (cropped && ImGui::IsItemHovered()) { if (cropped && ImGui::IsItemHovered()) {
@@ -505,11 +551,10 @@ void SendImagePopup::render(float time_delta) {
} }
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("send ->", {-FLT_MIN, TEXT_BASE_HEIGHT*2})) { if (ImGui::Button("send ->", {-FLT_MIN, TEXT_BASE_HEIGHT*2})) {
if (compress || cropped) { if (compress || cropped || scale_x != 1.f || scale_y != 1.f) {
// TODO: copy bad // TODO: copy bad
ImageLoaderI::ImageResult tmp_img; ImageLoaderI::ImageResult tmp_img;
if (cropped) { if (cropped) {
std::cout << "SIP: CROP!!!!!\n";
tmp_img = original_image.crop( tmp_img = original_image.crop(
crop_rect.x, crop_rect.x,
crop_rect.y, crop_rect.y,
@@ -520,6 +565,13 @@ void SendImagePopup::render(float time_delta) {
tmp_img = original_image; tmp_img = original_image;
} }
if (scale_x != 1.f || scale_y != 1.f) {
tmp_img = tmp_img.scale(
(int)std::ceil(crop_rect.w*scale_x),
(int)std::ceil(crop_rect.h*scale_y)
);
}
std::vector<uint8_t> new_data; std::vector<uint8_t> new_data;
// HACK: generic list // HACK: generic list

View File

@@ -36,6 +36,10 @@ struct SendImagePopup {
bool dragging_last_frame_ul {false}; bool dragging_last_frame_ul {false};
bool dragging_last_frame_lr {false}; bool dragging_last_frame_lr {false};
float scale_x {1.f};
float scale_y {1.f};
bool scale_tie {true};
// texture to render (orig img) // texture to render (orig img)
TextureEntry preview_image; TextureEntry preview_image;

View File

@@ -27,9 +27,7 @@
#include "./chat_gui/contact_list.hpp" #include "./chat_gui/contact_list.hpp"
#include "./media_meta_info_loader.hpp"
#include "./sdl_clipboard_utils.hpp" #include "./sdl_clipboard_utils.hpp"
#include "os_comps.hpp"
#include "./string_formatter_utils.hpp" #include "./string_formatter_utils.hpp"
@@ -42,7 +40,7 @@
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <variant> #include <iostream>
// TODO: split into msg and c // TODO: split into msg and c
namespace Components { namespace Components {
@@ -1074,7 +1072,7 @@ void ChatGui4::renderChatLog(Contact4 c, bool window_focused, const std::vector<
ImGui::EndTable(); ImGui::EndTable();
} }
if (ImGui::Shortcut(ImGuiKey_End, ImGuiInputFlags_RouteGlobal)) { if (ImGui::Shortcut(ImGuiKey_G | ImGuiMod_Shift, ImGuiInputFlags_RouteGlobal) || ImGui::Shortcut(ImGuiKey_End, ImGuiInputFlags_RouteGlobal)) {
ImGui::SetScrollHereY(1.f); ImGui::SetScrollHereY(1.f);
manually_scrolled = true; manually_scrolled = true;
} }
@@ -1420,7 +1418,7 @@ void ChatGui4::renderMessageBodyFile(Message3Registry& reg, const Message3 e) {
if (ImGui::IsItemVisible() && o.all_of<ObjComp::F::TagLocalHaveAll, ObjComp::F::SingleInfo, ObjComp::Ephemeral::BackendFile2>()) { if (ImGui::IsItemVisible() && o.all_of<ObjComp::F::TagLocalHaveAll, ObjComp::F::SingleInfo, ObjComp::Ephemeral::BackendFile2>()) {
ImGui::SetCursorPos(orig_curser_pos); // reset for actual img ImGui::SetCursorPos(orig_curser_pos); // reset for actual img
auto [id, img_width, img_height] = _msg_tc.get(Message3Handle{reg, e}); auto [id, img_width, img_height] = _msg_tc.get(Message3Handle{reg, e}, width, height);
// if cache gives 0s, fall back to frame dims (eg if pic not loaded yet) // if cache gives 0s, fall back to frame dims (eg if pic not loaded yet)
//if (img_width == 0 || img_height == 0) { //if (img_width == 0 || img_height == 0) {

View File

@@ -1,6 +1,9 @@
#include "./image_loader.hpp" #include "./image_loader.hpp"
#include <cassert> #include <cassert>
#include <cstdint>
#include "./image_scaler.hpp"
ImageLoaderI::ImageResult ImageLoaderI::ImageResult::crop(int32_t c_x, int32_t c_y, int32_t c_w, int32_t c_h) const { ImageLoaderI::ImageResult ImageLoaderI::ImageResult::crop(int32_t c_x, int32_t c_y, int32_t c_w, int32_t c_h) const {
// TODO: proper error handling // TODO: proper error handling
@@ -30,3 +33,23 @@ ImageLoaderI::ImageResult ImageLoaderI::ImageResult::crop(int32_t c_x, int32_t c
return new_image; return new_image;
} }
ImageLoaderI::ImageResult ImageLoaderI::ImageResult::scale(int32_t w, int32_t h) const {
assert(w > 0);
assert(h > 0);
ImageLoaderI::ImageResult new_image;
new_image.width = w;
new_image.height = h;
new_image.file_ext = file_ext;
for (const auto& input_frame : frames) {
auto& new_frame = new_image.frames.emplace_back();
new_frame.ms = input_frame.ms;
new_frame.data.resize(w*h*4);
image_scale(new_frame.data.data(), w, h, const_cast<uint8_t*>(input_frame.data.data()), width, height);
}
return new_image;
}

View File

@@ -28,7 +28,8 @@ struct ImageLoaderI {
// only positive values are valid // only positive values are valid
ImageResult crop(int32_t c_x, int32_t c_y, int32_t c_w, int32_t c_h) const; ImageResult crop(int32_t c_x, int32_t c_y, int32_t c_w, int32_t c_h) const;
// TODO: scale // only values > 0 are valid
ImageResult scale(int32_t w, int32_t h) const;
}; };
virtual ImageResult loadFromMemoryRGBA(const uint8_t* data, uint64_t data_size) = 0; virtual ImageResult loadFromMemoryRGBA(const uint8_t* data, uint64_t data_size) = 0;
}; };

170
src/image_scaler.cpp Normal file
View File

@@ -0,0 +1,170 @@
#include "./image_scaler.hpp"
#include <cmath>
#include <cassert>
// requires ColorTmp to have * and + operators
struct ColorCanvas8888;
struct ColorFloat4 {
float v[4]{};
ColorFloat4& operator*=(const float scalar) {
v[0] *= scalar;
v[1] *= scalar;
v[2] *= scalar;
v[3] *= scalar;
return *this;
}
ColorFloat4 operator*(const float scalar) const {
ColorFloat4 newcf = *this;
newcf.v[0] *= scalar;
newcf.v[1] *= scalar;
newcf.v[2] *= scalar;
newcf.v[3] *= scalar;
return newcf;
}
ColorFloat4& operator/=(const float scalar) {
v[0] /= scalar;
v[1] /= scalar;
v[2] /= scalar;
v[3] /= scalar;
return *this;
}
ColorFloat4& operator+=(const ColorFloat4& color) {
v[0] += color.v[0];
v[1] += color.v[1];
v[2] += color.v[2];
v[3] += color.v[3];
return *this;
}
};
struct ColorCanvas8888 {
uint8_t* ptr {nullptr};
ColorFloat4 operator[](size_t i) const {
return {
{
float(ptr[i*4+0])/255.f,
float(ptr[i*4+1])/255.f,
float(ptr[i*4+2])/255.f,
float(ptr[i*4+3])/255.f,
}
};
}
void set(size_t i, const ColorFloat4& color) {
ptr[i*4+0] = std::round(color.v[0]*255.f);
ptr[i*4+1] = std::round(color.v[1]*255.f);
ptr[i*4+2] = std::round(color.v[2]*255.f);
ptr[i*4+3] = std::round(color.v[3]*255.f);
}
};
template<typename ColorCanvas, typename ColorTmp>
constexpr void image_scale(ColorCanvas& dst, const int dst_w, const int dst_h, const ColorCanvas& src, const int src_w, const int src_h) {
// Box sampling - Imagine projecting the new, smaller pixels onto the larger source, covering multiple pixel.
for (int y = 0; y < dst_h; y++) {
for (int x = 0; x < dst_w; x++) {
// We perform a weighted mean.
ColorTmp color;
float weight_sum = 0.f;
// Walk from upper edge to bottom edge (vertical)
const float edge_up = ((float)y * src_h) / dst_h;
const float edge_down = ((y + 1.f) * src_h) / dst_h;
for (float frac_pos_y = edge_up; frac_pos_y < edge_down;) {
const int src_y = (int)std::floor(frac_pos_y); assert(src_y < src_h);
const float frac_y = 1.f - (frac_pos_y - src_y);
// Walk from left edge to right edge (horizontal)
const float edge_left = ((float)x * src_w) / dst_w;
const float edge_right = ((x + 1.f) * src_w) / dst_w;
for (float frac_pos_x = edge_left; frac_pos_x < edge_right;) {
const int src_x = (int)std::floor(frac_pos_x); assert(src_x < src_w);
const float frac_x = 1.f - (frac_pos_x - src_x);
const float src_pixel_weight = frac_x * frac_y;
//const ColorTmp pixel_color = ImGui::ColorConvertU32ToFloat4(src[src_y * src_w + src_x]);
const ColorTmp pixel_color = src[src_y * src_w + src_x];
color += pixel_color * src_pixel_weight;
weight_sum += src_pixel_weight;
frac_pos_x += frac_x;
}
frac_pos_y += frac_y;
}
color /= weight_sum;
dst.set(y * dst_w + x, color);
}
}
}
bool image_scale(uint8_t* dst, const int dst_w, const int dst_h, uint8_t* src, const int src_w, const int src_h) {
if (dst == nullptr || src == nullptr) {
return false;
}
if (dst_w == src_w && dst_h == src_h) {
assert(false && "fix me !");
return false;
}
ColorCanvas8888 dst_c{dst};
const ColorCanvas8888 src_c{src};
image_scale<ColorCanvas8888, ColorFloat4>(
dst_c,
dst_w, dst_h,
src_c,
src_w, src_h
);
return true;
}
bool image_scale(SDL_Surface* dst, SDL_Surface* src) {
if (dst == nullptr || src == nullptr) {
return false;
}
if (dst->format != src->format) {
return false;
}
// TODO: handle other numbers of components beside 4
if (
src->format != SDL_PIXELFORMAT_RGBA8888 &&
src->format != SDL_PIXELFORMAT_ARGB8888 &&
src->format != SDL_PIXELFORMAT_BGRA8888 &&
src->format != SDL_PIXELFORMAT_ABGR8888 &&
src->format != SDL_PIXELFORMAT_RGBX8888 &&
src->format != SDL_PIXELFORMAT_XRGB8888 &&
src->format != SDL_PIXELFORMAT_BGRX8888 &&
src->format != SDL_PIXELFORMAT_XBGR8888
) {
return false;
}
ColorCanvas8888 dst_c{reinterpret_cast<uint8_t*>(dst->pixels)};
const ColorCanvas8888 src_c{reinterpret_cast<uint8_t*>(src->pixels)};
image_scale<ColorCanvas8888, ColorFloat4>(
dst_c,
dst->w, dst->h,
src_c,
src->w, src->h
);
return true;
}

9
src/image_scaler.hpp Normal file
View File

@@ -0,0 +1,9 @@
#pragma once
#include <SDL3/SDL.h>
#include <cstdint>
bool image_scale(uint8_t* dst, const int dst_w, const int dst_h, uint8_t* src, const int src_w, const int src_h);
bool image_scale(SDL_Surface* dst, SDL_Surface* src);

View File

@@ -8,9 +8,8 @@
#include <solanaceae/message3/components.hpp> #include <solanaceae/message3/components.hpp>
#include "./os_comps.hpp"
#include <solanaceae/object_store/object_store.hpp> #include <solanaceae/object_store/object_store.hpp>
#include <solanaceae/object_store/meta_components_file.hpp>
#include <solanaceae/file/file2.hpp> #include <solanaceae/file/file2.hpp>
@@ -25,7 +24,7 @@ MessageImageLoader::MessageImageLoader(void) {
_image_loaders.push_back(std::make_unique<ImageLoaderSDLImage>()); _image_loaders.push_back(std::make_unique<ImageLoaderSDLImage>());
} }
TextureLoaderResult MessageImageLoader::load(TextureUploaderI& tu, Message3Handle m) { TextureLoaderResult MessageImageLoader::load(TextureUploaderI& tu, Message3Handle m, uint32_t w, uint32_t h) {
if (!static_cast<bool>(m)) { if (!static_cast<bool>(m)) {
return {std::nullopt}; return {std::nullopt};
} }
@@ -101,6 +100,17 @@ TextureLoaderResult MessageImageLoader::load(TextureUploaderI& tu, Message3Handl
TextureEntry new_entry; TextureEntry new_entry;
new_entry.timestamp_last_rendered = getTimeMS(); new_entry.timestamp_last_rendered = getTimeMS();
new_entry.current_texture = 0; new_entry.current_texture = 0;
new_entry.src_width = res.width;
new_entry.src_height = res.height;
if (w != 0 && h != 0 && w < res.width && h < res.height) {
res = res.scale(w, h);
}
new_entry.width = res.width;
new_entry.height = res.height;
for (const auto& [ms, data] : res.frames) { for (const auto& [ms, data] : res.frames) {
const auto n_t = tu.upload(data.data(), res.width, res.height); const auto n_t = tu.upload(data.data(), res.width, res.height);
if (n_t == 0) { if (n_t == 0) {
@@ -114,9 +124,6 @@ TextureLoaderResult MessageImageLoader::load(TextureUploaderI& tu, Message3Handl
continue; continue;
} }
new_entry.width = res.width;
new_entry.height = res.height;
std::cout << "MIL: loaded image file o:" << /*file_path*/ entt::to_integral(o.entity()) << "\n"; std::cout << "MIL: loaded image file o:" << /*file_path*/ entt::to_integral(o.entity()) << "\n";
return {new_entry}; return {new_entry};

View File

@@ -5,13 +5,11 @@
#include "./image_loader.hpp" #include "./image_loader.hpp"
#include "./texture_cache.hpp" #include "./texture_cache.hpp"
#include <optional>
class MessageImageLoader { class MessageImageLoader {
std::vector<std::unique_ptr<ImageLoaderI>> _image_loaders; std::vector<std::unique_ptr<ImageLoaderI>> _image_loaders;
public: public:
MessageImageLoader(void); MessageImageLoader(void);
TextureLoaderResult load(TextureUploaderI& tu, Message3Handle m); TextureLoaderResult load(TextureUploaderI& tu, Message3Handle m, uint32_t w, uint32_t h);
}; };

View File

@@ -51,8 +51,11 @@ TextureEntry generateTestAnim(TextureUploaderI& tu) {
new_entry.textures.emplace_back(n_t); new_entry.textures.emplace_back(n_t);
new_entry.frame_duration.emplace_back(250); new_entry.frame_duration.emplace_back(250);
} }
// TODO: 2x2?
new_entry.width = 0; new_entry.width = 0;
new_entry.height = 0; new_entry.height = 0;
new_entry.src_width = 0;
new_entry.src_height = 0;
return new_entry; return new_entry;
} }

View File

@@ -16,6 +16,10 @@
struct TextureEntry { struct TextureEntry {
uint32_t width {0}; uint32_t width {0};
uint32_t height {0}; uint32_t height {0};
uint32_t src_width {0};
uint32_t src_height {0};
std::vector<uint64_t> textures; std::vector<uint64_t> textures;
std::vector<uint32_t> frame_duration; // ms std::vector<uint32_t> frame_duration; // ms
size_t current_texture {0}; size_t current_texture {0};
@@ -28,6 +32,8 @@ struct TextureEntry {
TextureEntry(const TextureEntry& other) : TextureEntry(const TextureEntry& other) :
width(other.width), width(other.width),
height(other.height), height(other.height),
src_width(other.src_width),
src_height(other.src_height),
textures(other.textures), textures(other.textures),
frame_duration(other.frame_duration), frame_duration(other.frame_duration),
current_texture(other.current_texture), current_texture(other.current_texture),
@@ -39,6 +45,8 @@ struct TextureEntry {
TextureEntry& operator=(const TextureEntry& other) { TextureEntry& operator=(const TextureEntry& other) {
width = other.width; width = other.width;
height = other.height; height = other.height;
src_width = other.src_width;
src_height = other.src_height;
textures = other.textures; textures = other.textures;
frame_duration = other.frame_duration; frame_duration = other.frame_duration;
current_texture = other.current_texture; current_texture = other.current_texture;
@@ -97,7 +105,11 @@ struct TextureCache {
TextureEntry _default_texture; TextureEntry _default_texture;
entt::dense_map<KeyType, TextureEntry> _cache; entt::dense_map<KeyType, TextureEntry> _cache;
entt::dense_set<KeyType> _to_load; struct LoadDims {
uint32_t w{0};
uint32_t h{0};
};
entt::dense_map<KeyType, LoadDims> _to_load;
// to_reload // to_update? _marked_stale? // to_reload // to_update? _marked_stale?
const uint64_t ms_before_purge {60 * 1000ull}; const uint64_t ms_before_purge {60 * 1000ull};
@@ -126,21 +138,37 @@ struct TextureCache {
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
}; };
GetInfo get(const KeyType& key) { GetInfo get(const KeyType& key, uint32_t width = 0, uint32_t height = 0) {
auto it = _cache.find(key); auto it = _cache.find(key);
if (it != _cache.end()) { if (it != _cache.end()) {
// if scaled down AND smaller than requested, reload larger
if (
(width != 0 && height != 0) &&
(
(it->second.width < width && it->second.width < it->second.src_width) ||
(it->second.height < height && it->second.height < it->second.src_height)
)
) {
// TODO: only overwrite smaller dims (or combine max)
_to_load.insert({key, LoadDims{width, height}});
}
// return current texture either way
return { return {
it->second.template getID<TextureType>(), it->second.template getID<TextureType>(),
it->second.width, it->second.src_width,
it->second.height it->second.src_height
}; };
} else { } else {
_to_load.insert(key); // TODO: only overwrite smaller dims (or combine max)
_to_load.insert({key, LoadDims{width, height}});
// return fallback
return { return {
_default_texture.getID<TextureType>(), _default_texture.getID<TextureType>(),
_default_texture.width, _default_texture.src_width,
_default_texture.height _default_texture.src_height
}; };
} }
} }
@@ -153,7 +181,7 @@ struct TextureCache {
if (it == _cache.end()) { if (it == _cache.end()) {
return false; return false;
} }
_to_load.insert(key); _to_load.insert({key, {it->second.width, it->second.height}});
return true; return true;
} }
@@ -202,17 +230,18 @@ struct TextureCache {
bool workLoadQueue(void) { bool workLoadQueue(void) {
auto it = _to_load.cbegin(); auto it = _to_load.cbegin();
for (; it != _to_load.cend(); it++) { for (; it != _to_load.cend(); it++) {
auto new_entry_opt = _l.load(_tu, *it); const auto& load_key = it->first;
if (_cache.count(*it)) { auto new_entry_opt = _l.load(_tu, load_key, it->second.w, it->second.h);
if (_cache.count(load_key)) {
if (new_entry_opt.texture.has_value()) { if (new_entry_opt.texture.has_value()) {
auto old_entry = _cache.at(*it); // copy auto old_entry = _cache.at(load_key); // copy
assert(!old_entry.textures.empty()); assert(!old_entry.textures.empty());
for (const auto& tex_id : old_entry.textures) { for (const auto& tex_id : old_entry.textures) {
_tu.destroy(tex_id); _tu.destroy(tex_id);
} }
_cache.erase(*it); _cache.erase(load_key);
auto& new_entry = _cache[*it] = new_entry_opt.texture.value(); auto& new_entry = _cache[load_key] = new_entry_opt.texture.value();
// TODO: make update interface and let loader handle this // TODO: make update interface and let loader handle this
//new_entry.current_texture = old_entry.current_texture; // ?? //new_entry.current_texture = old_entry.current_texture; // ??
new_entry.rendered_this_frame = old_entry.rendered_this_frame; new_entry.rendered_this_frame = old_entry.rendered_this_frame;
@@ -228,8 +257,8 @@ struct TextureCache {
} }
} else { } else {
if (new_entry_opt.texture.has_value()) { if (new_entry_opt.texture.has_value()) {
_cache.emplace(*it, new_entry_opt.texture.value()); _cache.emplace(load_key, new_entry_opt.texture.value());
_cache.at(*it).rendered_this_frame = true; // ? _cache.at(load_key).rendered_this_frame = true; // ?
it = _to_load.erase(it); it = _to_load.erase(it);
// TODO: not a good idea? // TODO: not a good idea?

View File

@@ -195,7 +195,7 @@ static std::vector<uint8_t> generateToxIdenticon(const ToxKey& key) {
return pixels; return pixels;
} }
TextureLoaderResult ToxAvatarLoader::load(TextureUploaderI& tu, Contact4 c) { TextureLoaderResult ToxAvatarLoader::load(TextureUploaderI& tu, Contact4 c, uint32_t w, uint32_t h) {
const auto& cr = _cs.registry(); const auto& cr = _cs.registry();
if (!cr.valid(c)) { if (!cr.valid(c)) {
return {std::nullopt}; return {std::nullopt};
@@ -234,14 +234,23 @@ TextureLoaderResult ToxAvatarLoader::load(TextureUploaderI& tu, Contact4 c) {
TextureEntry new_entry; TextureEntry new_entry;
new_entry.timestamp_last_rendered = getTimeMS(); new_entry.timestamp_last_rendered = getTimeMS();
new_entry.current_texture = 0; new_entry.current_texture = 0;
new_entry.src_width = res.width;
new_entry.src_height = res.height;
if (w != 0 && h != 0 && w < res.width && h < res.height) {
res = res.scale(w, h);
}
new_entry.width = res.width;
new_entry.height = res.height;
for (const auto& [ms, data] : res.frames) { for (const auto& [ms, data] : res.frames) {
const auto n_t = tu.upload(data.data(), res.width, res.height); const auto n_t = tu.upload(data.data(), res.width, res.height);
new_entry.textures.push_back(n_t); new_entry.textures.push_back(n_t);
new_entry.frame_duration.push_back(ms); new_entry.frame_duration.push_back(ms);
} }
new_entry.width = res.width;
new_entry.height = res.height;
if (cr.all_of<Contact::Components::AvatarFile>(c)) { if (cr.all_of<Contact::Components::AvatarFile>(c)) {
std::cout << "TAL: loaded image file " << cr.get<Contact::Components::AvatarFile>(c).file_path << "\n"; std::cout << "TAL: loaded image file " << cr.get<Contact::Components::AvatarFile>(c).file_path << "\n";

View File

@@ -8,8 +8,6 @@
#include "./image_loader.hpp" #include "./image_loader.hpp"
#include "./texture_cache.hpp" #include "./texture_cache.hpp"
#include <optional>
class ToxAvatarLoader { class ToxAvatarLoader {
ContactStore4I& _cs; ContactStore4I& _cs;
ObjectStore2& _os; ObjectStore2& _os;
@@ -21,6 +19,6 @@ class ToxAvatarLoader {
public: public:
ToxAvatarLoader(ContactStore4I& cs, ObjectStore2& os); ToxAvatarLoader(ContactStore4I& cs, ObjectStore2& os);
TextureLoaderResult load(TextureUploaderI& tu, Contact4 c); TextureLoaderResult load(TextureUploaderI& tu, Contact4 c, uint32_t w, uint32_t h);
}; };

View File

@@ -79,18 +79,48 @@ void ToxUIUtils::render(void) {
_tc.runBootstrap(); _tc.runBootstrap();
} }
if (ImGui::MenuItem("connect node", nullptr, _show_dht_connect_node)) {
_show_dht_connect_node = !_show_dht_connect_node;
}
{ // self node info
bool either = false;
{
auto [port_opt, port_err] = _tc.toxSelfGetUDPPort();
if (port_opt.has_value()) {
either = true;
ImGui::TextDisabled("udp online; port: %d", port_opt.value());
} else {
ImGui::TextDisabled("udp disabled");
}
}
{
auto [port_opt, port_err] = _tc.toxSelfGetTCPPort();
if (port_opt.has_value()) {
either = true;
ImGui::TextDisabled("tcp relay server online; port: %d", port_opt.value());
} else {
ImGui::TextDisabled("tcp relay server disabled");
}
}
if (either && ImGui::MenuItem("copy own DHT id/pubkey")) {
ImGui::SetClipboardText(bin2hex(_tc.toxSelfGetDHTID()).c_str());
}
}
ImGui::EndMenu(); ImGui::EndMenu();
} }
switch (_tc.toxSelfGetConnectionStatus()) { switch (_tc.toxSelfGetConnectionStatus()) {
case TOX_CONNECTION_NONE: case TOX_CONNECTION_NONE:
ImGui::TextColored({1.0,0.5,0.5,0.8}, "Offline"); ImGui::TextColored({1.0,0.5,0.5,0.8}, "Disconnected");
break; break;
case TOX_CONNECTION_TCP: case TOX_CONNECTION_TCP:
ImGui::TextColored({0.0,1.0,0.8,0.8}, "Online-TCP"); ImGui::TextColored({0.0,1.0,0.8,0.8}, "Connected-TCP");
break; break;
case TOX_CONNECTION_UDP: case TOX_CONNECTION_UDP:
ImGui::TextColored({0.3,1.0,0.0,0.8}, "Online-UDP"); ImGui::TextColored({0.3,1.0,0.0,0.8}, "Connected-UDP");
break; break;
} }
@@ -236,5 +266,81 @@ void ToxUIUtils::render(void) {
} }
ImGui::End(); ImGui::End();
} }
if (_show_dht_connect_node) {
if (ImGui::Begin("Tox connect DHT node", &_show_dht_connect_node)) {
ImGui::BeginDisabled();
ImGui::TextWrapped(
"Here you can manually connect to a DHT node (or/and tcp-relay) by address and id/pubkey.\n"
"This is equivalent to what 'DHT Bootstrapping' does, but not with hardcoded nodes.\n"
"Keep in mind that your own DHT id/pubkey changes everytime you start the program, unlike dedicated bootstrap nodes.\n"
"If DNS querries where not disabled at launch, domain names can be used too."
"A public list can be found at: nodes.tox.chat\n"
);
ImGui::EndDisabled();
static std::string addr;
static uint16_t port {33445};
static char pubkey[TOX_PUBLIC_KEY_SIZE*2 + 1]; // 1 for null terminator
if (ImGui::BeginTable("node", 2, ImGuiTableFlags_SizingFixedFit)) {
ImGui::TableSetupColumn(nullptr, ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn(nullptr, ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextColumn();
ImGui::TextUnformatted("address");
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
ImGui::InputText("##address", &addr);
ImGui::TableNextColumn();
ImGui::TextUnformatted("port");
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
ImGui::InputScalar("##port", ImGuiDataType_U16, &port);
ImGui::TableNextColumn();
ImGui::TextUnformatted("pubkey");
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
ImGui::InputText("##pubkey", pubkey, TOX_PUBLIC_KEY_SIZE*2+1);
// add as
// - udp dht node (default)
// - udp dht node + tcp relay
// - tcp relay
ImGui::EndTable();
}
static std::string last_error;
bool valid_input = !addr.empty() && port != 0;
if (!valid_input) ImGui::BeginDisabled();
if (ImGui::Button("connect")) {
std::vector<uint8_t> bin_pubkey = hex2bin(std::string_view{pubkey, TOX_PUBLIC_KEY_SIZE*2});
last_error.clear();
{
Tox_Err_Bootstrap err = _tc.toxBootstrap(addr, port, bin_pubkey);
if (err != Tox_Err_Bootstrap::TOX_ERR_BOOTSTRAP_OK) {
last_error += "add udp node failed with " + std::to_string(err) + "\n";
}
}
{
Tox_Err_Bootstrap err = _tc.toxAddTcpRelay(addr, port, bin_pubkey);
if (err != Tox_Err_Bootstrap::TOX_ERR_BOOTSTRAP_OK) {
last_error += "add tcp relay failed with " + std::to_string(err) + "\n";
}
}
}
if (!valid_input) ImGui::EndDisabled();
if (!last_error.empty()) {
ImGui::TextUnformatted(last_error.c_str());
}
}
ImGui::End();
}
} }

View File

@@ -11,6 +11,7 @@ class ToxUIUtils {
bool _show_add_friend_window {false}; bool _show_add_friend_window {false};
bool _show_add_group_window {false}; bool _show_add_group_window {false};
bool _show_new_group_window {false}; bool _show_new_group_window {false};
bool _show_dht_connect_node {false};
ToxClient& _tc; ToxClient& _tc;
ToxContactModel2& _tcm; ToxContactModel2& _tcm;