tomato/src/main_screen.cpp

282 lines
7.5 KiB
C++
Raw Normal View History

2023-07-26 12:24:18 +02:00
#include "./main_screen.hpp"
#include <imgui/imgui.h>
2023-07-26 20:09:57 +02:00
#include <SDL3/SDL.h>
2023-07-26 12:24:18 +02:00
#include <memory>
#include <cmath>
2023-07-26 12:24:18 +02:00
MainScreen::MainScreen(SDL_Renderer* renderer_, std::string save_path, std::string save_password, std::vector<std::string> plugins) :
2023-07-26 20:09:57 +02:00
renderer(renderer_),
rmm(cr),
2023-07-29 20:51:32 +02:00
mts(rmm),
tc(save_path, save_password),
2023-11-13 15:14:30 +01:00
tpi(tc.getTox()),
ad(tc),
2023-07-26 20:09:57 +02:00
tcm(cr, tc, tc),
tmm(rmm, cr, tcm, tc, tc),
ttm(rmm, cr, tcm, tc, tc),
tffom(cr, rmm, tcm, tc, tc),
2023-08-02 19:24:51 +02:00
mmil(rmm),
tam(rmm, cr, conf),
2023-07-28 18:03:45 +02:00
sdlrtu(renderer_),
cg(conf, rmm, cr, sdlrtu),
sw(conf),
2023-11-13 16:23:49 +01:00
tuiu(tc, conf),
tdch(tpi)
2023-07-26 20:09:57 +02:00
{
2023-07-26 12:55:50 +02:00
tel.subscribeAll(tc);
conf.set("tox", "save_file_path", save_path);
{ // name stuff
auto name = tc.toxSelfGetName();
if (name.empty()) {
name = "tomato";
}
conf.set("tox", "name", name);
tc.setSelfName(name); // TODO: this is ugly
}
// TODO: remove
std::cout << "own address: " << tc.toxSelfGetAddressStr() << "\n";
{ // setup plugin instances
g_provideInstance<ConfigModelI>("ConfigModelI", "host", &conf);
2024-01-18 00:32:11 +01:00
g_provideInstance<Contact3Registry>("Contact3Registry", "1", "host", &cr);
2023-07-26 12:55:50 +02:00
g_provideInstance<RegistryMessageModel>("RegistryMessageModel", "host", &rmm);
g_provideInstance<ToxI>("ToxI", "host", &tc);
2023-11-13 15:14:30 +01:00
g_provideInstance<ToxPrivateI>("ToxPrivateI", "host", &tpi);
2023-07-26 12:55:50 +02:00
g_provideInstance<ToxEventProviderI>("ToxEventProviderI", "host", &tc);
g_provideInstance<ToxContactModel2>("ToxContactModel2", "host", &tcm);
2023-07-26 12:55:50 +02:00
// TODO: pm?
// graphics
2024-01-18 18:36:29 +01:00
g_provideInstance("ImGuiContext", ImGui::GetVersion(), "host", ImGui::GetCurrentContext());
2023-07-26 20:09:57 +02:00
g_provideInstance<TextureUploaderI>("TextureUploaderI", "host", &sdlrtu);
2023-07-26 12:55:50 +02:00
}
for (const auto& ppath : plugins) {
if (!pm.add(ppath)) {
std::cerr << "MS error: loading plugin '" << ppath << "' failed!\n";
// thow?
assert(false && "failed to load plugin");
}
}
2023-07-26 12:55:50 +02:00
conf.dump();
2023-07-26 12:24:18 +02:00
}
2023-07-26 20:09:57 +02:00
MainScreen::~MainScreen(void) {
}
2023-07-30 15:10:26 +02:00
bool MainScreen::handleEvent(SDL_Event& e) {
2023-10-18 14:23:27 +02:00
if (e.type == SDL_EVENT_DROP_FILE) {
2024-01-17 22:39:51 +01:00
std::cout << "DROP FILE: " << e.drop.data << "\n";
cg.sendFilePath(e.drop.data);
2024-01-07 22:20:40 +01:00
_render_interval = 1.f/60.f; // TODO: magic
_time_since_event = 0.f;
2023-10-18 14:23:27 +02:00
return true; // TODO: forward return succ from sendFilePath()
}
if (
e.type == SDL_EVENT_WINDOW_MINIMIZED ||
e.type == SDL_EVENT_WINDOW_HIDDEN ||
e.type == SDL_EVENT_WINDOW_OCCLUDED // does this trigger on partial occlusion?
) {
auto* window = SDL_GetWindowFromID(e.window.windowID);
auto* event_renderer = SDL_GetRenderer(window);
if (event_renderer != nullptr && event_renderer == renderer) {
// our window is now obstructed
if (_window_hidden_ts < e.window.timestamp) {
_window_hidden_ts = e.window.timestamp;
_window_hidden = true;
//std::cout << "TOMAT: window hidden " << e.window.timestamp << "\n";
}
}
return true; // forward?
}
if (
e.type == SDL_EVENT_WINDOW_SHOWN ||
e.type == SDL_EVENT_WINDOW_RESTORED ||
e.type == SDL_EVENT_WINDOW_EXPOSED
) {
auto* window = SDL_GetWindowFromID(e.window.windowID);
auto* event_renderer = SDL_GetRenderer(window);
if (event_renderer != nullptr && event_renderer == renderer) {
if (_window_hidden_ts <= e.window.timestamp) {
_window_hidden_ts = e.window.timestamp;
2024-01-06 15:13:45 +01:00
if (_window_hidden) {
// if window was previously hidden, we shorten the wait for the next frame
_render_interval = 1.f/60.f;
}
_window_hidden = false;
//std::cout << "TOMAT: window shown " << e.window.timestamp << "\n";
}
}
2024-01-07 22:20:40 +01:00
_render_interval = 1.f/60.f; // TODO: magic
_time_since_event = 0.f;
return true; // forward?
}
2024-01-06 18:23:06 +01:00
if (
_fps_perf_mode <= 1 && (
2024-01-07 22:20:40 +01:00
// those are all the events imgui polls
2024-01-06 18:23:06 +01:00
e.type == SDL_EVENT_MOUSE_MOTION ||
e.type == SDL_EVENT_MOUSE_WHEEL ||
e.type == SDL_EVENT_MOUSE_BUTTON_DOWN ||
e.type == SDL_EVENT_MOUSE_BUTTON_UP ||
e.type == SDL_EVENT_TEXT_INPUT ||
e.type == SDL_EVENT_KEY_DOWN ||
e.type == SDL_EVENT_KEY_UP ||
e.type == SDL_EVENT_WINDOW_MOUSE_ENTER ||
e.type == SDL_EVENT_WINDOW_MOUSE_LEAVE ||
e.type == SDL_EVENT_WINDOW_FOCUS_GAINED ||
e.type == SDL_EVENT_WINDOW_FOCUS_LOST
)
) {
_render_interval = 1.f/60.f; // TODO: magic
2024-01-07 22:20:40 +01:00
_time_since_event = 0.f;
2024-01-06 18:23:06 +01:00
}
2023-07-30 15:10:26 +02:00
return false;
}
2024-01-07 16:33:08 +01:00
Screen* MainScreen::render(float time_delta, bool&) {
// HACK: render the tomato main window first, with proper flags set.
// flags need to be set the first time begin() is called.
// and plugins are run before the main cg is run.
{
// TODO: maybe render cg earlier? or move the main window out of cg?
constexpr auto bg_window_flags =
ImGuiWindowFlags_NoDecoration |
ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoSavedSettings |
ImGuiWindowFlags_MenuBar |
ImGuiWindowFlags_NoBringToFrontOnFocus;
ImGui::Begin("tomato", nullptr, bg_window_flags);
ImGui::End();
}
2024-01-07 16:33:08 +01:00
const float pm_interval = pm.render(time_delta); // render
2023-07-29 20:51:32 +02:00
2024-01-07 16:33:08 +01:00
cg.render(time_delta); // render
sw.render(); // render
tuiu.render(); // render
tdch.render(); // render
2023-07-28 18:03:45 +02:00
{ // main window menubar injection
if (ImGui::Begin("tomato")) {
if (ImGui::BeginMenuBar()) {
// ImGui::Separator(); // why do we not need this????
if (ImGui::BeginMenu("Performance")) {
{ // fps
2024-01-06 18:23:06 +01:00
const auto targets = "normal\0reduced\0powersave\0";
ImGui::SetNextItemWidth(ImGui::GetFontSize()*10);
ImGui::Combo("fps mode", &_fps_perf_mode, targets, 4);
}
{ // compute
2024-01-13 18:38:12 +01:00
const auto targets = "normal\0powersave\0extreme powersave\0";
ImGui::SetNextItemWidth(ImGui::GetFontSize()*10);
ImGui::Combo("compute mode", &_compute_perf_mode, targets, 4);
2024-01-07 16:33:08 +01:00
ImGui::SetItemTooltip("Limiting compute can slow down things like filetransfers!");
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Settings")) {
if (ImGui::MenuItem("ImGui Style Editor")) {
_show_tool_style_editor = true;
}
ImGui::EndMenu();
}
ImGui::EndMenuBar();
}
}
ImGui::End();
}
if (_show_tool_style_editor) {
if (ImGui::Begin("Dear ImGui Style Editor", &_show_tool_style_editor)) {
ImGui::ShowStyleEditor();
}
ImGui::End();
}
if constexpr (false) {
2023-09-29 18:15:18 +02:00
ImGui::ShowDemoWindow();
2023-07-26 12:55:50 +02:00
}
2023-07-26 12:24:18 +02:00
if (
2024-01-07 16:33:08 +01:00
_fps_perf_mode > 1 // TODO: magic
) {
2024-01-07 16:33:08 +01:00
// powersave forces 250ms
_render_interval = 1.f/4.f;
2024-01-07 16:33:08 +01:00
} else if (
2024-01-07 22:20:40 +01:00
_time_since_event > 1.f && ( // 1sec cool down
_fps_perf_mode == 1 || // TODO: magic
_window_hidden
)
2024-01-07 16:33:08 +01:00
) {
2024-02-03 19:07:14 +01:00
_render_interval = std::min<float>(1.f/1.f, pm_interval);
} else {
2024-01-07 16:33:08 +01:00
_render_interval = std::min<float>(1.f/60.f, pm_interval);
}
2024-01-07 22:20:40 +01:00
_time_since_event += time_delta;
2024-01-05 14:47:08 +01:00
return nullptr;
}
Screen* MainScreen::tick(float time_delta, bool& quit) {
2024-01-07 16:33:08 +01:00
quit = !tc.iterate(); // compute
tcm.iterate(time_delta); // compute
const float fo_interval = tffom.tick(time_delta);
2024-01-07 16:33:08 +01:00
tam.iterate(); // compute
const float pm_interval = pm.tick(time_delta); // compute
tdch.tick(time_delta); // compute
mts.iterate(); // compute
2024-01-13 18:38:12 +01:00
_min_tick_interval = std::min<float>(
// HACK: pow by 1.6 to increase 50 -> ~500 (~522)
// and it does not change 1
std::pow(tc.toxIterationInterval(), 1.6f)/1000.f,
2024-01-13 18:38:12 +01:00
pm_interval
2024-01-05 14:47:08 +01:00
);
_min_tick_interval = std::min<float>(
_min_tick_interval,
fo_interval
);
2023-07-26 20:09:57 +02:00
//std::cout << "MS: min tick interval: " << _min_tick_interval << "\n";
2024-01-13 18:38:12 +01:00
switch (_compute_perf_mode) {
// normal 1ms lower bound
case 0: _min_tick_interval = std::max<float>(_min_tick_interval, 0.001f); break;
// in powersave fix the lowerbound to 100ms
case 1: _min_tick_interval = std::max<float>(_min_tick_interval, 0.1f); break;
// extreme 2s
case 2: _min_tick_interval = std::max<float>(_min_tick_interval, 2.f); break;
default: std::cerr << "unknown compute perf mode\n"; std::exit(-1);
}
2023-07-26 12:24:18 +02:00
return nullptr;
}