Compare commits
	
		
			5 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| ff5dbaffc0 | |||
| b56d581e4b | |||
| aa661aaaa7 | |||
| cc3f430bab | |||
| 139db5b03b | 
							
								
								
									
										2
									
								
								external/solanaceae_contact
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								external/solanaceae_contact
									
									
									
									
										vendored
									
									
								
							 Submodule external/solanaceae_contact updated: 2d73c7272c...9ca6adee4f
									
								
							
							
								
								
									
										2
									
								
								external/solanaceae_message3
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								external/solanaceae_message3
									
									
									
									
										vendored
									
									
								
							 Submodule external/solanaceae_message3 updated: 20af7dd705...a1f5add8d3
									
								
							
							
								
								
									
										2
									
								
								external/solanaceae_util
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								external/solanaceae_util
									
									
									
									
										vendored
									
									
								
							 Submodule external/solanaceae_util updated: 390b123fb7...d304d719e9
									
								
							@@ -37,7 +37,7 @@ namespace Components {
 | 
			
		||||
 | 
			
		||||
} // Components
 | 
			
		||||
 | 
			
		||||
static float lerp(float a, float b, float t) {
 | 
			
		||||
static constexpr float lerp(float a, float b, float t) {
 | 
			
		||||
	return a + t * (b - a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -121,8 +121,10 @@ ChatGui4::ChatGui4(
 | 
			
		||||
	ConfigModelI& conf,
 | 
			
		||||
	RegistryMessageModel& rmm,
 | 
			
		||||
	Contact3Registry& cr,
 | 
			
		||||
	TextureUploaderI& tu
 | 
			
		||||
) : _conf(conf), _rmm(rmm), _cr(cr), _tal(_cr), _contact_tc(_tal, tu), _msg_tc(_mil, tu), _sip(tu) {
 | 
			
		||||
	TextureUploaderI& tu,
 | 
			
		||||
	ContactTextureCache& contact_tc,
 | 
			
		||||
	MessageTextureCache& msg_tc
 | 
			
		||||
) : _conf(conf), _rmm(rmm), _cr(cr), _contact_tc(contact_tc), _msg_tc(msg_tc), _sip(tu) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ChatGui4::~ChatGui4(void) {
 | 
			
		||||
@@ -136,20 +138,7 @@ ChatGui4::~ChatGui4(void) {
 | 
			
		||||
	//}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChatGui4::render(float time_delta) {
 | 
			
		||||
	if (!_cr.storage<Contact::Components::TagAvatarInvalidate>().empty()) { // handle force-reloads for avatars
 | 
			
		||||
		std::vector<Contact3> to_purge;
 | 
			
		||||
		_cr.view<Contact::Components::TagAvatarInvalidate>().each([&to_purge](const Contact3 c) {
 | 
			
		||||
			to_purge.push_back(c);
 | 
			
		||||
		});
 | 
			
		||||
		_cr.remove<Contact::Components::TagAvatarInvalidate>(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();
 | 
			
		||||
	_msg_tc.update();
 | 
			
		||||
 | 
			
		||||
float ChatGui4::render(float time_delta) {
 | 
			
		||||
	_fss.render();
 | 
			
		||||
	_sip.render(time_delta);
 | 
			
		||||
 | 
			
		||||
@@ -627,8 +616,7 @@ void ChatGui4::render(float time_delta) {
 | 
			
		||||
	}
 | 
			
		||||
	ImGui::End();
 | 
			
		||||
 | 
			
		||||
	_contact_tc.workLoadQueue();
 | 
			
		||||
	_msg_tc.workLoadQueue();
 | 
			
		||||
	return 1000.f; // TODO: higher min fps?
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChatGui4::sendFilePath(const char* file_path) {
 | 
			
		||||
@@ -749,7 +737,11 @@ void ChatGui4::renderMessageBodyFile(Message3Registry& reg, const Message3 e) {
 | 
			
		||||
	) {
 | 
			
		||||
		if (ImGui::Button("save to")) {
 | 
			
		||||
			_fss.requestFile(
 | 
			
		||||
				[](const auto& path) -> bool { return std::filesystem::is_directory(path); },
 | 
			
		||||
				[](std::filesystem::path& path) -> bool {
 | 
			
		||||
					// remove file path
 | 
			
		||||
					path.remove_filename();
 | 
			
		||||
					return std::filesystem::is_directory(path);
 | 
			
		||||
				},
 | 
			
		||||
				[this, ®, e](const auto& path) {
 | 
			
		||||
					if (reg.valid(e)) { // still valid
 | 
			
		||||
						// TODO: trim file?
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,8 @@
 | 
			
		||||
#include "./message_image_loader.hpp"
 | 
			
		||||
#include "./file_selector.hpp"
 | 
			
		||||
#include "./send_image_popup.hpp"
 | 
			
		||||
#include "entt/container/dense_map.hpp"
 | 
			
		||||
 | 
			
		||||
#include <entt/container/dense_map.hpp>
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <vector>
 | 
			
		||||
@@ -17,15 +18,16 @@
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
using ContactTextureCache = TextureCache<void*, Contact3, ToxAvatarLoader>;
 | 
			
		||||
using MessageTextureCache = TextureCache<void*, Message3Handle, MessageImageLoader>;
 | 
			
		||||
 | 
			
		||||
class ChatGui4 {
 | 
			
		||||
	ConfigModelI& _conf;
 | 
			
		||||
	RegistryMessageModel& _rmm;
 | 
			
		||||
	Contact3Registry& _cr;
 | 
			
		||||
 | 
			
		||||
	ToxAvatarLoader _tal;
 | 
			
		||||
	TextureCache<void*, Contact3, ToxAvatarLoader> _contact_tc;
 | 
			
		||||
	MessageImageLoader _mil;
 | 
			
		||||
	TextureCache<void*, Message3Handle, MessageImageLoader> _msg_tc;
 | 
			
		||||
	ContactTextureCache& _contact_tc;
 | 
			
		||||
	MessageTextureCache& _msg_tc;
 | 
			
		||||
 | 
			
		||||
	FileSelector _fss;
 | 
			
		||||
	SendImagePopup _sip;
 | 
			
		||||
@@ -52,12 +54,14 @@ class ChatGui4 {
 | 
			
		||||
			ConfigModelI& conf,
 | 
			
		||||
			RegistryMessageModel& rmm,
 | 
			
		||||
			Contact3Registry& cr,
 | 
			
		||||
			TextureUploaderI& tu
 | 
			
		||||
			TextureUploaderI& tu,
 | 
			
		||||
			ContactTextureCache& contact_tc,
 | 
			
		||||
			MessageTextureCache& msg_tc
 | 
			
		||||
		);
 | 
			
		||||
		~ChatGui4(void);
 | 
			
		||||
 | 
			
		||||
	public:
 | 
			
		||||
		void render(float time_delta);
 | 
			
		||||
		float render(float time_delta);
 | 
			
		||||
 | 
			
		||||
	public:
 | 
			
		||||
		bool any_unread {false};
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ FileSelector::FileSelector(void) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSelector::requestFile(
 | 
			
		||||
	std::function<bool(const std::filesystem::path& path)>&& is_valid,
 | 
			
		||||
	std::function<bool(std::filesystem::path& path)>&& is_valid,
 | 
			
		||||
	std::function<void(const std::filesystem::path& path)>&& on_choose,
 | 
			
		||||
	std::function<void(void)>&& on_cancel
 | 
			
		||||
) {
 | 
			
		||||
@@ -77,7 +77,9 @@ void FileSelector::render(void) {
 | 
			
		||||
			if (current_path.has_parent_path()) {
 | 
			
		||||
				if (ImGui::TableNextColumn()) {
 | 
			
		||||
					if (ImGui::Selectable("D##..", false, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap)) {
 | 
			
		||||
						_current_file_path = _current_file_path.parent_path();
 | 
			
		||||
						// the first "parent_path()" only removes the filename and the ending "/"
 | 
			
		||||
						_current_file_path = _current_file_path.parent_path().parent_path() / "";
 | 
			
		||||
						//_current_file_path = _current_file_path.remove_filename().parent_path() / "";
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ struct FileSelector {
 | 
			
		||||
 | 
			
		||||
	bool _open_popup {false};
 | 
			
		||||
 | 
			
		||||
	std::function<bool(const std::filesystem::path& path)> _is_valid = [](auto){ return true; };
 | 
			
		||||
	std::function<bool(std::filesystem::path& path)> _is_valid = [](auto){ return true; };
 | 
			
		||||
	std::function<void(const std::filesystem::path& path)> _on_choose = [](auto){};
 | 
			
		||||
	std::function<void(void)> _on_cancel = [](){};
 | 
			
		||||
 | 
			
		||||
@@ -18,8 +18,9 @@ struct FileSelector {
 | 
			
		||||
		FileSelector(void);
 | 
			
		||||
 | 
			
		||||
		// TODO: supply hints
 | 
			
		||||
		// HACK: until we supply hints, is_valid can modify
 | 
			
		||||
		void requestFile(
 | 
			
		||||
			std::function<bool(const std::filesystem::path& path)>&& is_valid,
 | 
			
		||||
			std::function<bool(std::filesystem::path& path)>&& is_valid,
 | 
			
		||||
			std::function<void(const std::filesystem::path& path)>&& on_choose,
 | 
			
		||||
			std::function<void(void)>&& on_cancel
 | 
			
		||||
		);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,7 @@
 | 
			
		||||
#include "./main_screen.hpp"
 | 
			
		||||
 | 
			
		||||
#include <solanaceae/contact/components.hpp>
 | 
			
		||||
 | 
			
		||||
#include <imgui/imgui.h>
 | 
			
		||||
 | 
			
		||||
#include <SDL3/SDL.h>
 | 
			
		||||
@@ -21,7 +23,11 @@ MainScreen::MainScreen(SDL_Renderer* renderer_, std::string save_path, std::stri
 | 
			
		||||
	mmil(rmm),
 | 
			
		||||
	tam(rmm, cr, conf),
 | 
			
		||||
	sdlrtu(renderer_),
 | 
			
		||||
	cg(conf, rmm, cr, sdlrtu),
 | 
			
		||||
	tal(cr),
 | 
			
		||||
	contact_tc(tal, sdlrtu),
 | 
			
		||||
	mil(),
 | 
			
		||||
	msg_tc(mil, sdlrtu),
 | 
			
		||||
	cg(conf, rmm, cr, sdlrtu, contact_tc, msg_tc),
 | 
			
		||||
	sw(conf),
 | 
			
		||||
	tuiu(tc, conf),
 | 
			
		||||
	tdch(tpi)
 | 
			
		||||
@@ -168,7 +174,22 @@ Screen* MainScreen::render(float time_delta, bool&) {
 | 
			
		||||
 | 
			
		||||
	const float pm_interval = pm.render(time_delta); // render
 | 
			
		||||
 | 
			
		||||
	cg.render(time_delta); // render
 | 
			
		||||
	// TODO: move this somewhere else!!!
 | 
			
		||||
	// needs both tal and tc <.<
 | 
			
		||||
	if (!cr.storage<Contact::Components::TagAvatarInvalidate>().empty()) { // handle force-reloads for avatars
 | 
			
		||||
		std::vector<Contact3> to_purge;
 | 
			
		||||
		cr.view<Contact::Components::TagAvatarInvalidate>().each([&to_purge](const Contact3 c) {
 | 
			
		||||
			to_purge.push_back(c);
 | 
			
		||||
		});
 | 
			
		||||
		cr.remove<Contact::Components::TagAvatarInvalidate>(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
 | 
			
		||||
	const float ctc_interval = contact_tc.update();
 | 
			
		||||
	const float msgtc_interval = msg_tc.update();
 | 
			
		||||
 | 
			
		||||
	const float cg_interval = cg.render(time_delta); // render
 | 
			
		||||
	sw.render(); // render
 | 
			
		||||
	tuiu.render(); // render
 | 
			
		||||
	tdch.render(); // render
 | 
			
		||||
@@ -217,20 +238,136 @@ Screen* MainScreen::render(float time_delta, bool&) {
 | 
			
		||||
		ImGui::ShowDemoWindow();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (
 | 
			
		||||
		_fps_perf_mode > 1 // TODO: magic
 | 
			
		||||
	) {
 | 
			
		||||
		// powersave forces 250ms
 | 
			
		||||
		_render_interval = 1.f/4.f;
 | 
			
		||||
	} else if (
 | 
			
		||||
		_time_since_event > 1.f && ( // 1sec cool down
 | 
			
		||||
			_fps_perf_mode == 1 || // TODO: magic
 | 
			
		||||
			_window_hidden
 | 
			
		||||
	float tc_unfinished_queue_interval;
 | 
			
		||||
	{ // load rendered but not loaded textures
 | 
			
		||||
		bool unfinished_work_queue = contact_tc.workLoadQueue();
 | 
			
		||||
		unfinished_work_queue = unfinished_work_queue || msg_tc.workLoadQueue();
 | 
			
		||||
 | 
			
		||||
		if (unfinished_work_queue) {
 | 
			
		||||
			tc_unfinished_queue_interval = 0.1f; // so we can get images loaded faster
 | 
			
		||||
		} else {
 | 
			
		||||
			tc_unfinished_queue_interval = 1.f; // TODO: higher min fps?
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// calculate interval for next frame
 | 
			
		||||
	// normal:
 | 
			
		||||
	//  - if < 1.5sec since last event
 | 
			
		||||
	//    - min all and clamp(1/60, 1/1)
 | 
			
		||||
	//  - if < 30sec since last event
 | 
			
		||||
	//    - min all (anim + everything else) clamp(1/60, 1/1) (maybe less?)
 | 
			
		||||
	//  - else
 | 
			
		||||
	//    - min without anim and clamp(1/60, 1/1) (maybe more?)
 | 
			
		||||
	// reduced:
 | 
			
		||||
	//  - if < 1sec since last event
 | 
			
		||||
	//    - min all and clamp(1/60, 1/1)
 | 
			
		||||
	//  - if < 10sec since last event
 | 
			
		||||
	//    - min all (anim + everything else) clamp(1/10, 1/1)
 | 
			
		||||
	//  - else
 | 
			
		||||
	//    - min without anim and max clamp(1/10, 1/1)
 | 
			
		||||
	// powersave:
 | 
			
		||||
	//  - if < 0sec since last event
 | 
			
		||||
	//    - (ignored)
 | 
			
		||||
	//  - if < 1sec since last event
 | 
			
		||||
	//    - min all (anim + everything else) clamp(1/8, 1/1)
 | 
			
		||||
	//  - else
 | 
			
		||||
	//    - min without anim and clamp(1/1, 1/1)
 | 
			
		||||
	struct PerfProfileRender {
 | 
			
		||||
		float low_delay_window {1.5f};
 | 
			
		||||
		float low_delay_min {1.f/60.f};
 | 
			
		||||
		float low_delay_max {1.f/60.f};
 | 
			
		||||
 | 
			
		||||
		float mid_delay_window {30.f};
 | 
			
		||||
		float mid_delay_min {1.f/60.f};
 | 
			
		||||
		float mid_delay_max {1.f/2.f};
 | 
			
		||||
 | 
			
		||||
		// also when main window hidden
 | 
			
		||||
		float else_delay_min {1.f/60.f};
 | 
			
		||||
		float else_delay_max {1.f/2.f};
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	const static PerfProfileRender normalPerfProfile{
 | 
			
		||||
		//1.5f,		// low_delay_window
 | 
			
		||||
		//1.f/60.f,	// low_delay_min
 | 
			
		||||
		//1.f/60.f,	// low_delay_max
 | 
			
		||||
 | 
			
		||||
		//30.f,		// mid_delay_window
 | 
			
		||||
		//1.f/60.f,	// mid_delay_min
 | 
			
		||||
		//1.f/2.f,	// mid_delay_max
 | 
			
		||||
 | 
			
		||||
		//1.f/60.f,	// else_delay_min
 | 
			
		||||
		//1.f/2.f,	// else_delay_max
 | 
			
		||||
	};
 | 
			
		||||
	const static PerfProfileRender reducedPerfProfile{
 | 
			
		||||
		1.f,		// low_delay_window
 | 
			
		||||
		1.f/60.f,	// low_delay_min
 | 
			
		||||
		1.f/30.f,	// low_delay_max
 | 
			
		||||
 | 
			
		||||
		10.f,		// mid_delay_window
 | 
			
		||||
		1.f/10.f,	// mid_delay_min
 | 
			
		||||
		1.f/4.f,	// mid_delay_max
 | 
			
		||||
 | 
			
		||||
		1.f/10.f,	// else_delay_min
 | 
			
		||||
		1.f,		// else_delay_max
 | 
			
		||||
	};
 | 
			
		||||
	// TODO: fix powersave by adjusting it in the events handler (make ppr member)
 | 
			
		||||
	const static PerfProfileRender powersavePerfProfile{
 | 
			
		||||
		// no window -> ignore first case
 | 
			
		||||
		0.f,		// low_delay_window
 | 
			
		||||
		1.f,		// low_delay_min
 | 
			
		||||
		1.f,		// low_delay_max
 | 
			
		||||
 | 
			
		||||
		1.f,		// mid_delay_window
 | 
			
		||||
		1.f/8.f,	// mid_delay_min
 | 
			
		||||
		1.f/4.f,	// mid_delay_max
 | 
			
		||||
 | 
			
		||||
		1.f,		// else_delay_min
 | 
			
		||||
		1.f,		// else_delay_max
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	const PerfProfileRender& curr_profile =
 | 
			
		||||
		// TODO: magic
 | 
			
		||||
		_fps_perf_mode > 1
 | 
			
		||||
		? powersavePerfProfile
 | 
			
		||||
		: (
 | 
			
		||||
			_fps_perf_mode == 1
 | 
			
		||||
			? reducedPerfProfile
 | 
			
		||||
			: normalPerfProfile
 | 
			
		||||
		)
 | 
			
		||||
	) {
 | 
			
		||||
		_render_interval = std::min<float>(1.f/1.f, pm_interval);
 | 
			
		||||
	;
 | 
			
		||||
 | 
			
		||||
	// min over non animations in all cases
 | 
			
		||||
	_render_interval = std::min<float>(pm_interval, cg_interval);
 | 
			
		||||
	_render_interval = std::min<float>(_render_interval, tc_unfinished_queue_interval);
 | 
			
		||||
 | 
			
		||||
	// low delay time window
 | 
			
		||||
	if (!_window_hidden && _time_since_event < curr_profile.low_delay_window) {
 | 
			
		||||
		_render_interval = std::min<float>(_render_interval, ctc_interval);
 | 
			
		||||
		_render_interval = std::min<float>(_render_interval, msgtc_interval);
 | 
			
		||||
 | 
			
		||||
		_render_interval = std::clamp(
 | 
			
		||||
			_render_interval,
 | 
			
		||||
			curr_profile.low_delay_min,
 | 
			
		||||
			curr_profile.low_delay_max
 | 
			
		||||
		);
 | 
			
		||||
	// mid delay time window
 | 
			
		||||
	} else if (!_window_hidden && _time_since_event < curr_profile.mid_delay_window) {
 | 
			
		||||
		_render_interval = std::min<float>(_render_interval, ctc_interval);
 | 
			
		||||
		_render_interval = std::min<float>(_render_interval, msgtc_interval);
 | 
			
		||||
 | 
			
		||||
		_render_interval = std::clamp(
 | 
			
		||||
			_render_interval,
 | 
			
		||||
			curr_profile.mid_delay_min,
 | 
			
		||||
			curr_profile.mid_delay_max
 | 
			
		||||
		);
 | 
			
		||||
	// timed out or window hidden
 | 
			
		||||
	} else {
 | 
			
		||||
		_render_interval = std::min<float>(1.f/60.f, pm_interval);
 | 
			
		||||
		// no animation timing here
 | 
			
		||||
		_render_interval = std::clamp(
 | 
			
		||||
			_render_interval,
 | 
			
		||||
			curr_profile.else_delay_min,
 | 
			
		||||
			curr_profile.else_delay_max
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_time_since_event += time_delta;
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,10 @@
 | 
			
		||||
#include "./tox_avatar_manager.hpp"
 | 
			
		||||
 | 
			
		||||
#include "./sdlrenderer_texture_uploader.hpp"
 | 
			
		||||
#include "./texture_cache.hpp"
 | 
			
		||||
#include "./tox_avatar_loader.hpp"
 | 
			
		||||
#include "./message_image_loader.hpp"
 | 
			
		||||
 | 
			
		||||
#include "./chat_gui4.hpp"
 | 
			
		||||
#include "./settings_window.hpp"
 | 
			
		||||
#include "./tox_ui_utils.hpp"
 | 
			
		||||
@@ -61,6 +65,11 @@ struct MainScreen final : public Screen {
 | 
			
		||||
	SDLRendererTextureUploader sdlrtu;
 | 
			
		||||
	//OpenGLTextureUploader ogltu;
 | 
			
		||||
 | 
			
		||||
	ToxAvatarLoader tal;
 | 
			
		||||
	TextureCache<void*, Contact3, ToxAvatarLoader> contact_tc;
 | 
			
		||||
	MessageImageLoader mil;
 | 
			
		||||
	TextureCache<void*, Message3Handle, MessageImageLoader> msg_tc;
 | 
			
		||||
 | 
			
		||||
	ChatGui4 cg;
 | 
			
		||||
	SettingsWindow sw;
 | 
			
		||||
	ToxUIUtils tuiu;
 | 
			
		||||
@@ -85,7 +94,7 @@ struct MainScreen final : public Screen {
 | 
			
		||||
	// 0 - normal
 | 
			
		||||
	// 1 - reduced
 | 
			
		||||
	// 2 - power save
 | 
			
		||||
	int _fps_perf_mode {1};
 | 
			
		||||
	int _fps_perf_mode {0};
 | 
			
		||||
	// 0 - normal
 | 
			
		||||
	// 1 - power save
 | 
			
		||||
	int _compute_perf_mode {0};
 | 
			
		||||
 
 | 
			
		||||
@@ -2,8 +2,9 @@
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <limits>
 | 
			
		||||
 | 
			
		||||
void TextureEntry::doAnimation(const int64_t ts_now) {
 | 
			
		||||
int64_t TextureEntry::doAnimation(const int64_t ts_now) {
 | 
			
		||||
	if (frame_duration.size() > 1) { // is animation
 | 
			
		||||
		do { // why is this loop so ugly
 | 
			
		||||
			const int64_t duration = getDuration();
 | 
			
		||||
@@ -11,11 +12,13 @@ void TextureEntry::doAnimation(const int64_t ts_now) {
 | 
			
		||||
				timestamp_last_rendered += duration;
 | 
			
		||||
				next();
 | 
			
		||||
			} else {
 | 
			
		||||
				break;
 | 
			
		||||
				// return ts for next frame
 | 
			
		||||
				return timestamp_last_rendered + duration;
 | 
			
		||||
			}
 | 
			
		||||
		} while(true);
 | 
			
		||||
		} while (true);
 | 
			
		||||
	} else {
 | 
			
		||||
		timestamp_last_rendered = ts_now;
 | 
			
		||||
		return std::numeric_limits<int64_t>::max(); // static image
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -50,7 +50,8 @@ struct TextureEntry {
 | 
			
		||||
		current_texture = (current_texture + 1) % frame_duration.size();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void doAnimation(const int64_t ts_now);
 | 
			
		||||
	// returns ts for next frame
 | 
			
		||||
	int64_t doAnimation(const int64_t ts_now);
 | 
			
		||||
 | 
			
		||||
	template<typename TextureType>
 | 
			
		||||
	TextureType getID(void) {
 | 
			
		||||
@@ -133,14 +134,16 @@ struct TextureCache {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void update(void) {
 | 
			
		||||
	float update(void) {
 | 
			
		||||
		const uint64_t ts_now = Message::getTimeMS();
 | 
			
		||||
		uint64_t ts_min_next = ts_now + ms_before_purge;
 | 
			
		||||
 | 
			
		||||
		std::vector<KeyType> to_purge;
 | 
			
		||||
		for (auto&& [key, te] : _cache) {
 | 
			
		||||
			if (te.rendered_this_frame) {
 | 
			
		||||
				te.doAnimation(ts_now);
 | 
			
		||||
				const uint64_t ts_next = te.doAnimation(ts_now);
 | 
			
		||||
				te.rendered_this_frame = false;
 | 
			
		||||
				ts_min_next = std::min(ts_min_next, ts_next);
 | 
			
		||||
			} else if (_cache.size() > min_count_before_purge && ts_now - te.timestamp_last_rendered >= ms_before_purge) {
 | 
			
		||||
				to_purge.push_back(key);
 | 
			
		||||
			}
 | 
			
		||||
@@ -148,7 +151,10 @@ struct TextureCache {
 | 
			
		||||
 | 
			
		||||
		invalidate(to_purge);
 | 
			
		||||
 | 
			
		||||
		// we ignore the default texture ts :)
 | 
			
		||||
		_default_texture.doAnimation(ts_now);
 | 
			
		||||
 | 
			
		||||
		return (ts_min_next - ts_now) / 1000.f;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void invalidate(const std::vector<KeyType>& to_purge) {
 | 
			
		||||
@@ -162,16 +168,22 @@ struct TextureCache {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void workLoadQueue(void) {
 | 
			
		||||
		for (auto it = _to_load.begin(); it != _to_load.end(); it++) {
 | 
			
		||||
	// returns true if there is still work queued up
 | 
			
		||||
	bool workLoadQueue(void) {
 | 
			
		||||
		auto it = _to_load.begin();
 | 
			
		||||
		for (; it != _to_load.end(); it++) {
 | 
			
		||||
			auto new_entry_opt = _l.load(_tu, *it);
 | 
			
		||||
			if (new_entry_opt.has_value()) {
 | 
			
		||||
				_cache.emplace(*it, new_entry_opt.value());
 | 
			
		||||
				_to_load.erase(it);
 | 
			
		||||
				// TODO: not a good idea
 | 
			
		||||
				it = _to_load.erase(it);
 | 
			
		||||
 | 
			
		||||
				// TODO: not a good idea?
 | 
			
		||||
				break; // end load from queue/onlyload 1 per update
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// peak
 | 
			
		||||
		return it != _to_load.end();
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user