From f9caa75aa7cd668ea72b7a10d6afaf1b71201c6d Mon Sep 17 00:00:00 2001 From: Bruno Herbelin Date: Sun, 16 Apr 2023 14:51:58 +0200 Subject: [PATCH] New source toolbar, cleanup other toolbars and help window Split Metrics and Source editor as two separate toolbars. Removed keyboard shortcut for metrics and sticky note. Ensure log notification are visible. --- src/Log.cpp | 5 +- src/Settings.cpp | 6 + src/Settings.h | 6 + src/UserInterfaceManager.cpp | 755 +++++++++++++++++++++++------------ src/UserInterfaceManager.h | 13 +- 5 files changed, 532 insertions(+), 253 deletions(-) diff --git a/src/Log.cpp b/src/Log.cpp index a4f9882..e39d69b 100644 --- a/src/Log.cpp +++ b/src/Log.cpp @@ -256,8 +256,9 @@ void Log::Render(bool *showWarnings) ImGui::SetNextWindowPos( ImVec2(pos, y), ImGuiCond_Always ); ImGui::SetNextWindowSize( ImVec2(width, height), ImGuiCond_Always ); - ImGui::SetNextWindowBgAlpha(0.8f); // Transparent background - if (ImGui::Begin("##notification", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav )) + ImGui::SetNextWindowBgAlpha(0.9f); // opaque background + if (ImGui::Begin("##notification", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | + ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNav )) { ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + width); for (list::iterator it=notifications.begin(); it != notifications.end(); ++it) { diff --git a/src/Settings.cpp b/src/Settings.cpp index e3fce5b..8b6e1ac 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -162,6 +162,9 @@ void Settings::Save(uint64_t runtime) widgetsNode->SetAttribute("stats_corner", application.widget.stats_corner); widgetsNode->SetAttribute("logs", application.widget.logs); widgetsNode->SetAttribute("toolbox", application.widget.toolbox); + widgetsNode->SetAttribute("source_toolbar", application.widget.source_toolbar); + widgetsNode->SetAttribute("source_toolbar_mode", application.widget.source_toolbar_mode); + widgetsNode->SetAttribute("source_toolbar_border", application.widget.source_toolbar_border); pRoot->InsertEndChild(widgetsNode); // Render @@ -441,6 +444,9 @@ void Settings::Load() widgetsNode->QueryIntAttribute("stats_corner", &application.widget.stats_corner); widgetsNode->QueryBoolAttribute("logs", &application.widget.logs); widgetsNode->QueryBoolAttribute("toolbox", &application.widget.toolbox); + widgetsNode->QueryBoolAttribute("source_toolbar", &application.widget.source_toolbar); + widgetsNode->QueryIntAttribute("source_toolbar_mode", &application.widget.source_toolbar_mode); + widgetsNode->QueryIntAttribute("source_toolbar_border", &application.widget.source_toolbar_border); } // Render diff --git a/src/Settings.h b/src/Settings.h index 28bbd5f..4a54215 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -32,6 +32,9 @@ struct WidgetsConfig int shader_editor_view; bool toolbox; bool help; + bool source_toolbar; + int source_toolbar_border; + int source_toolbar_mode; WidgetsConfig() { stats = false; @@ -52,6 +55,9 @@ struct WidgetsConfig shader_editor_view = -1; inputs = false; inputs_view = -1; + source_toolbar = false; + source_toolbar_mode = 0; + source_toolbar_border = -1; } }; diff --git a/src/UserInterfaceManager.cpp b/src/UserInterfaceManager.cpp index 4e72a9e..2016dfd 100644 --- a/src/UserInterfaceManager.cpp +++ b/src/UserInterfaceManager.cpp @@ -96,10 +96,8 @@ TextEditor _editor; #include "UserInterfaceManager.h" #define PLOT_CIRCLE_SEGMENTS 64 #define PLOT_ARRAY_SIZE 180 -#define LABEL_AUTO_MEDIA_PLAYER ICON_FA_USER_CIRCLE " User selection" -#define LABEL_STORE_SELECTION " Create batch" -#define LABEL_EDIT_FADING ICON_FA_RANDOM " Fade in & out" -#define LABEL_VIDEO_SEQUENCE " Encode an image sequence" +#define WINDOW_TOOLBOX_ALPHA 0.35f +#define WINDOW_TOOLBOX_DIST_TO_BORDER 10.f // utility functions void ShowAboutGStreamer(bool* p_open); @@ -303,7 +301,7 @@ void UserInterface::handleKeyboard() } else if (ImGui::IsKeyPressed( Control::layoutKey(GLFW_KEY_H), false )) { // Helper - Settings::application.widget.help = !Settings::application.widget.help; + Settings::application.widget.help = true; } else if (ImGui::IsKeyPressed( Control::layoutKey(GLFW_KEY_E), false )) { // Shader Editor @@ -355,15 +353,9 @@ void UserInterface::handleKeyboard() if (clipboard != nullptr && strlen(clipboard) > 0) Mixer::manager().paste(clipboard); } - else if (ImGui::IsKeyPressed( Control::layoutKey(GLFW_KEY_M), false )) { - Settings::application.widget.stats = !Settings::application.widget.stats; - } else if (ImGui::IsKeyPressed( Control::layoutKey(GLFW_KEY_I), false )) { Settings::application.widget.inputs = !Settings::application.widget.inputs; } - else if (ImGui::IsKeyPressed( Control::layoutKey(GLFW_KEY_N), false ) && shift_modifier_active) { - Mixer::manager().session()->addNote(); - } } // No CTRL modifier @@ -878,6 +870,12 @@ void UserInterface::Render() &Settings::application.widget.stats_corner, &Settings::application.widget.stats_mode); + // source editor + if (Settings::application.widget.source_toolbar) + RenderSourceToolbar(&Settings::application.widget.source_toolbar, + &Settings::application.widget.source_toolbar_border, + &Settings::application.widget.source_toolbar_mode); + if ( WorkspaceWindow::clear()) ImGui::PopStyleVar(); // All other windows are simply not rendered if workspace is clear @@ -1227,280 +1225,542 @@ void UserInterface::RenderOutputView() } +enum MetricsFlags_ +{ + Metrics_none = 0, + Metrics_framerate = 1, + Metrics_ram = 2, + Metrics_gpu = 4, + Metrics_session = 8, + Metrics_runtime = 16, + Metrics_lifetime = 32 +}; + void UserInterface::RenderMetrics(bool *p_open, int* p_corner, int *p_mode) { - if (!p_corner || !p_open) + if (!p_open || !p_corner || !p_mode) return; - const float DISTANCE = 10.0f; - int corner = *p_corner; + if (*p_mode == Metrics_none) + *p_mode = Metrics_framerate; + ImGuiIO& io = ImGui::GetIO(); - if (corner != -1) - { - ImVec2 window_pos = ImVec2((corner & 1) ? io.DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? io.DisplaySize.y - DISTANCE : DISTANCE); - ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f); + if (*p_corner != -1) { + ImVec2 window_pos = ImVec2((*p_corner & 1) ? io.DisplaySize.x - WINDOW_TOOLBOX_DIST_TO_BORDER : WINDOW_TOOLBOX_DIST_TO_BORDER, + (*p_corner & 2) ? io.DisplaySize.y - WINDOW_TOOLBOX_DIST_TO_BORDER : WINDOW_TOOLBOX_DIST_TO_BORDER); + ImVec2 window_pos_pivot = ImVec2((*p_corner & 1) ? 1.0f : 0.0f, (*p_corner & 2) ? 1.0f : 0.0f); ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot); } - ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background + ImGui::SetNextWindowBgAlpha(WINDOW_TOOLBOX_ALPHA); // Transparent background - if (!ImGui::Begin("Metrics", NULL, (corner != -1 ? ImGuiWindowFlags_NoMove : 0) | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) + if (!ImGui::Begin("Metrics", NULL, (*p_corner != -1 ? ImGuiWindowFlags_NoMove : 0) | + ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) { ImGui::End(); return; } - // combo selection of mode, with fixed width to display enough text - ImGui::SetNextItemWidth( 8.4f * ImGui::GetTextLineHeight()); - ImGui::Combo("##mode", p_mode, - ICON_FA_TACHOMETER_ALT " Performance\0" - ICON_FA_HOURGLASS_HALF " Runtime\0" - ICON_FA_VECTOR_SQUARE " Source\0"); - - ImGui::SameLine(0, IMGUI_SAME_LINE); + // title + ImGui::Text( MENU_METRICS ); + ImGui::SameLine(0, 2.2f * ImGui::GetTextLineHeightWithSpacing()); if (ImGuiToolkit::IconButton(5,8)) ImGui::OpenPopup("metrics_menu"); - ImGui::Spacing(); - ImGui::Spacing(); - float sliderwidth = 6.4f * ImGui::GetTextLineHeightWithSpacing(); - - if (*p_mode > 1) { - Source *s = Mixer::manager().currentSource(); - if (s) { - std::ostringstream info; - info << s->name() << ": "; - - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.f, 2.f)); - // - // ALPHA - // - float v = s->alpha() * 100.f; - ImGui::SetNextItemWidth(sliderwidth); - if ( ImGui::DragFloat("##Alpha", &v, 0.1f, 0.f, 100.f, "%.1f%%") ) - s->call(new SetAlpha(v*0.01f), true); - if ( ImGui::IsItemDeactivatedAfterEdit() ) { - info << "Alpha " << std::fixed << std::setprecision(3) << v; - Action::manager().store(info.str()); - } - ImGui::SameLine(0, IMGUI_SAME_LINE); - if (ImGuiToolkit::TextButton("Alpha")) { - s->call(new SetAlpha(1.f), true); - info << "Alpha " << std::fixed << std::setprecision(3) << 0.f; - Action::manager().store(info.str()); - } - - // - // POSITION COORDINATES - // - Group *n = s->group(View::GEOMETRY); - glm::vec3 out = Mixer::manager().session()->frame()->resolution(); - float vec[2] = { n->translation_.x * out.y * 0.5f, n->translation_.y * out.y * 0.5f}; - ImGui::SetNextItemWidth(sliderwidth); - if ( ImGui::DragFloat2("##Pos", vec, 1.0f, -MAX_SCALE * out.x, MAX_SCALE * out.x, "%.0f px") ) { - n->translation_.x = vec[0] / (0.5f * out.y); - n->translation_.y = vec[1] / (0.5f * out.y); - s->touch(); - } - if ( ImGui::IsItemDeactivatedAfterEdit() ){ - info << "Position " << std::setprecision(3) << n->translation_.x << ", " << n->translation_.y; - Action::manager().store(info.str()); - } - ImGui::SameLine(0, IMGUI_SAME_LINE); - if (ImGuiToolkit::TextButton("Pos")) { - n->translation_.x = 0.f; - n->translation_.y = 0.f; - s->touch(); - info << "Position " << std::setprecision(3) << n->translation_.x << ", " << n->translation_.y; - Action::manager().store(info.str()); - } - - // - // SCALE - // - static bool lock_scale = true; - float ar_scale = n->scale_.x / n->scale_.y; - // SCALE X - v = n->scale_.x * out.x; - ImGui::SetNextItemWidth( 2.7f * ImGui::GetTextLineHeightWithSpacing() ); - if ( ImGui::DragFloat("##ScaleX", &v, 1.f, -MAX_SCALE * out.x, MAX_SCALE * out.x, "%.0f") ) { - if (v > 10.f) { - n->scale_.x = v / out.x; - if (lock_scale) - n->scale_.y = n->scale_.x / ar_scale; - s->touch(); - } - } - if ( ImGui::IsItemDeactivatedAfterEdit() ){ - info << "Scale " << std::setprecision(3) << n->scale_.x << " x " << n->scale_.y; - Action::manager().store(info.str()); - } - // SCALE LOCK ASPECT RATIO - ImGui::SameLine(0, 0); - ImGuiToolkit::IconToggle(5,1,6,1, &lock_scale ); - ImGui::SameLine(0, 0); - // SCALE Y - v = n->scale_.y * out.y; - ImGui::SetNextItemWidth( 2.7f * ImGui::GetTextLineHeightWithSpacing() ); - if ( ImGui::DragFloat("##ScaleY", &v, 1.f, -MAX_SCALE * out.y, MAX_SCALE * out.y, "%.0f") ) { - if (v > 10.f) { - n->scale_.y = v / out.y; - if (lock_scale) - n->scale_.x = n->scale_.y * ar_scale; - s->touch(); - } - } - if ( ImGui::IsItemDeactivatedAfterEdit() ){ - info << "Scale " << std::setprecision(3) << n->scale_.x << " x " << n->scale_.y; - Action::manager().store(info.str()); - } - ImGui::SameLine(0, IMGUI_SAME_LINE); - if (ImGuiToolkit::TextButton("Size")) { - n->scale_.x = 1.f; - n->scale_.y = 1.f; - s->touch(); - info << "Scale " << std::setprecision(3) << n->scale_.x << ", " << n->scale_.y; - Action::manager().store(info.str()); - } - - // - // ROTATION ANGLE - // - float v_deg = n->rotation_.z * 360.0f / (2.f*M_PI); - ImGui::SetNextItemWidth(sliderwidth); - if ( ImGui::DragFloat("##Angle", &v_deg, 0.02f, -180.f, 180.f, "%.2f" UNICODE_DEGREE) ) { - n->rotation_.z = v_deg * (2.f*M_PI) / 360.0f; - s->touch(); - } - if ( ImGui::IsItemDeactivatedAfterEdit() ) { - info << "Angle " << std::setprecision(3) << n->rotation_.z * 180.f / M_PI; - Action::manager().store(info.str()); - } - ImGui::SameLine(0, IMGUI_SAME_LINE); - if (ImGuiToolkit::TextButton("Angle")) { - n->rotation_.z = 0.f; - s->touch(); - info << "Angle " << std::setprecision(3) << n->rotation_.z * 180.f / M_PI; - Action::manager().store(info.str()); - } - - ImGui::PopStyleVar(); + // read Memory info every 1/2 second + static long ram = 0; + static glm::ivec2 gpu(INT_MAX, INT_MAX); + { + static GTimer *timer = g_timer_new (); + double elapsed = g_timer_elapsed (timer, NULL); + if ( elapsed > 0.5 ){ + ram = SystemToolkit::memory_usage(); + gpu = Rendering::manager().getGPUMemoryInformation(); + g_timer_start(timer); } - else - ImGui::Text("No source selected"); } - else if (*p_mode > 0) { + static char dummy_str[256]; + uint64_t time = Runtime(); - static char dummy_str[] = "00:00:00.00"; - sliderwidth = 5.6f * ImGui::GetTextLineHeightWithSpacing(); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.f, 2.5f)); - - ImGuiToolkit::PushFont(ImGuiToolkit::FONT_BOLD); - sprintf(dummy_str, "%s", GstToolkit::time_to_string(Mixer::manager().session()->runtime(), GstToolkit::TIME_STRING_READABLE).c_str()); - ImGui::SetNextItemWidth(sliderwidth); - ImGui::InputText("##dummy", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly); - ImGui::PopFont(); - ImGui::SameLine(0, IMGUI_SAME_LINE); - ImGui::Text("Session"); - if (ImGui::IsItemHovered()) - ImGuiToolkit::ToolTip("Runtime since session load"); - - ImGuiToolkit::PushFont(ImGuiToolkit::FONT_BOLD); - uint64_t time = Runtime(); - sprintf(dummy_str, "%s", GstToolkit::time_to_string(time, GstToolkit::TIME_STRING_READABLE).c_str()); - ImGui::SetNextItemWidth(sliderwidth); - ImGui::InputText("##dummy2", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly); - ImGui::PopFont(); - ImGui::SameLine(0, IMGUI_SAME_LINE); - ImGui::Text("Runtime"); - if (ImGui::IsItemHovered()) - ImGuiToolkit::ToolTip("Runtime since vimix started"); - - ImGuiToolkit::PushFont(ImGuiToolkit::FONT_BOLD); - time += Settings::application.total_runtime; - sprintf(dummy_str, "%s", GstToolkit::time_to_string(time, GstToolkit::TIME_STRING_READABLE).c_str()); - ImGui::SetNextItemWidth(sliderwidth); - ImGui::InputText("##dummy3", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly); - ImGui::PopFont(); - ImGui::SameLine(0, IMGUI_SAME_LINE); - ImGui::Text("Lifetime"); - if (ImGui::IsItemHovered()) - ImGuiToolkit::ToolTip("Accumulated runtime of vimix\nsince its installation"); - - ImGui::PopStyleVar(); - } - else { - - // read Memory info every 1/2 second - static long ram = 0; - static glm::ivec2 gpu(INT_MAX, INT_MAX); - { - static GTimer *timer = g_timer_new (); - double elapsed = g_timer_elapsed (timer, NULL); - if ( elapsed > 0.5 ){ - ram = SystemToolkit::memory_usage(); - gpu = Rendering::manager().getGPUMemoryInformation(); - g_timer_start(timer); - } - } - static char dummy_str[256]; - - sliderwidth = 5.6f * ImGui::GetTextLineHeightWithSpacing(); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.f, 2.5f)); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.f, 2.5f)); + const float _width = 4.f * ImGui::GetTextLineHeightWithSpacing(); + if (*p_mode & Metrics_framerate) { ImGuiToolkit::PushFont(ImGuiToolkit::FONT_BOLD); sprintf(dummy_str, "%.1f", io.Framerate); - ImGui::SetNextItemWidth(sliderwidth); + ImGui::SetNextItemWidth(_width); ImGui::InputText("##dummy", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly); ImGui::PopFont(); ImGui::SameLine(0, IMGUI_SAME_LINE); ImGui::Text("FPS"); if (ImGui::IsItemHovered()) ImGuiToolkit::ToolTip("Frames per second"); + } + if (*p_mode & Metrics_ram) { ImGuiToolkit::PushFont(ImGuiToolkit::FONT_BOLD); sprintf(dummy_str, "%s", BaseToolkit::byte_to_string( ram ).c_str()); - ImGui::SetNextItemWidth(sliderwidth); + ImGui::SetNextItemWidth(_width); ImGui::InputText("##dummy2", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly); ImGui::PopFont(); ImGui::SameLine(0, IMGUI_SAME_LINE); ImGui::Text("RAM"); if (ImGui::IsItemHovered()) ImGuiToolkit::ToolTip("Amount of physical memory\nused by vimix"); - - // GPU RAM if available - if (gpu.x < INT_MAX && gpu.x > 0) { - ImGuiToolkit::PushFont(ImGuiToolkit::FONT_BOLD); - // got free and max GPU RAM (nvidia) - if (gpu.y < INT_MAX && gpu.y > 0) - sprintf(dummy_str, "%s", BaseToolkit::byte_to_string( long(gpu.y-gpu.x) * 1024 ).c_str()); - // got used GPU RAM (ati) - else - sprintf(dummy_str, "%s", BaseToolkit::byte_to_string( long(gpu.x) * 1024 ).c_str()); - ImGui::SetNextItemWidth(sliderwidth); - ImGui::InputText("##dummy3", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly); - ImGui::PopFont(); - ImGui::SameLine(0, IMGUI_SAME_LINE); - ImGui::Text("GPU"); - if (ImGui::IsItemHovered()) - ImGuiToolkit::ToolTip("Total memory used in GPU"); - } - ImGui::PopStyleVar(); } + // GPU RAM if available + if (gpu.x < INT_MAX && gpu.x > 0 && *p_mode & Metrics_gpu) { + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_BOLD); + // got free and max GPU RAM (nvidia) + if (gpu.y < INT_MAX && gpu.y > 0) + sprintf(dummy_str, "%s", BaseToolkit::byte_to_string( long(gpu.y-gpu.x) * 1024 ).c_str()); + // got used GPU RAM (ati) + else + sprintf(dummy_str, "%s", BaseToolkit::byte_to_string( long(gpu.x) * 1024 ).c_str()); + ImGui::SetNextItemWidth(_width); + ImGui::InputText("##dummy3", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly); + ImGui::PopFont(); + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::Text("GPU"); + if (ImGui::IsItemHovered()) + ImGuiToolkit::ToolTip("Total memory used in GPU"); + } + + if (*p_mode & Metrics_session) { + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_BOLD); + sprintf(dummy_str, "%s", GstToolkit::time_to_string(Mixer::manager().session()->runtime(), GstToolkit::TIME_STRING_READABLE).c_str()); + ImGui::SetNextItemWidth(_width); + ImGui::InputText("##dummy", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly); + ImGui::PopFont(); + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::Text("Session"); + if (ImGui::IsItemHovered()) + ImGuiToolkit::ToolTip("Runtime since session load"); + } + + if (*p_mode & Metrics_runtime) { + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_BOLD); + sprintf(dummy_str, "%s", GstToolkit::time_to_string(time, GstToolkit::TIME_STRING_READABLE).c_str()); + ImGui::SetNextItemWidth(_width); + ImGui::InputText("##dummy2", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly); + ImGui::PopFont(); + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::Text("Runtime"); + if (ImGui::IsItemHovered()) + ImGuiToolkit::ToolTip("Runtime since vimix started"); + } + + if (*p_mode & Metrics_lifetime) { + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_BOLD); + time += Settings::application.total_runtime; + sprintf(dummy_str, "%s", GstToolkit::time_to_string(time, GstToolkit::TIME_STRING_READABLE).c_str()); + ImGui::SetNextItemWidth(_width); + ImGui::InputText("##dummy3", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly); + ImGui::PopFont(); + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::Text("Lifetime"); + if (ImGui::IsItemHovered()) + ImGuiToolkit::ToolTip("Accumulated runtime of vimix\nsince its installation"); + } + + ImGui::PopStyleVar(); + if (ImGui::BeginPopup("metrics_menu")) { - ImGui::TextDisabled( MENU_METRICS ); - if (ImGui::MenuItem( ICON_FA_ANGLE_UP " Top", NULL, corner == 1)) *p_corner = 1; - if (ImGui::MenuItem( ICON_FA_ANGLE_DOWN " Bottom", NULL, corner == 3)) *p_corner = 3; - if (ImGui::MenuItem( ICON_FA_EXPAND_ARROWS_ALT " Free position", NULL, corner == -1)) *p_corner = -1; - if (p_open && ImGui::MenuItem( ICON_FA_TIMES " Close")) *p_open = false; + if (ImGui::MenuItem( "Framerate", NULL, *p_mode & Metrics_framerate)) + *p_mode ^= Metrics_framerate; + if (ImGui::MenuItem( "RAM", NULL, *p_mode & Metrics_ram)) + *p_mode ^= Metrics_ram; + // GPU RAM if available + if (gpu.x < INT_MAX && gpu.x > 0) + if (ImGui::MenuItem( "GPU", NULL, *p_mode & Metrics_gpu)) + *p_mode ^= Metrics_gpu; + if (ImGui::MenuItem( "Session time", NULL, *p_mode & Metrics_session)) + *p_mode ^= Metrics_session; + if (ImGui::MenuItem( "Runtime", NULL, *p_mode & Metrics_runtime)) + *p_mode ^= Metrics_runtime; + if (ImGui::MenuItem( "Lifetime", NULL, *p_mode & Metrics_lifetime)) + *p_mode ^= Metrics_lifetime; + + ImGui::Separator(); + + if (ImGui::MenuItem( ICON_FA_ANGLE_UP " Top right", NULL, *p_corner == 1)) + *p_corner = 1; + if (ImGui::MenuItem( ICON_FA_ANGLE_DOWN " Bottom right", NULL, *p_corner == 3)) + *p_corner = 3; + if (ImGui::MenuItem( ICON_FA_EXPAND_ARROWS_ALT " Free position", NULL, *p_corner == -1)) + *p_corner = -1; + if (p_open && ImGui::MenuItem( ICON_FA_TIMES " Close")) + *p_open = false; + ImGui::EndPopup(); } ImGui::End(); } +enum SourceToolbarFlags_ +{ + SourceToolbar_none = 0, + SourceToolbar_linkar = 1, + SourceToolbar_autohide = 2 +}; + +void UserInterface::RenderSourceToolbar(bool *p_open, int* p_border, int *p_mode) { + + if (!p_open || !p_border || !p_mode) + return; + + Source *s = Mixer::manager().currentSource(); + if (s || !(*p_mode & SourceToolbar_autohide) ) { + + std::ostringstream info; + const glm::vec3 out = Mixer::manager().session()->frame()->resolution(); + const char *tooltip_lock[2] = {"Width & height not linked", "Width & height linked"}; + + // + // horizontal layout for top and bottom placements + // + if (*p_border > 0) { + + ImGuiIO& io = ImGui::GetIO(); + ImVec2 window_pos = ImVec2((*p_border & 1) ? io.DisplaySize.x * 0.5 : WINDOW_TOOLBOX_DIST_TO_BORDER, + (*p_border & 2) ? io.DisplaySize.y - WINDOW_TOOLBOX_DIST_TO_BORDER : WINDOW_TOOLBOX_DIST_TO_BORDER); + ImVec2 window_pos_pivot = ImVec2((*p_border & 1) ? 0.5f : 0.0f, (*p_border & 2) ? 1.0f : 0.0f); + ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot); + ImGui::SetNextWindowBgAlpha(WINDOW_TOOLBOX_ALPHA); // Transparent background + + if (!ImGui::Begin("SourceToolbarfixed", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | + ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoNav)) + { + ImGui::End(); + return; + } + + const float sliderwidth = 3.f * ImGui::GetTextLineHeightWithSpacing(); + + if (s) { + + // get info on source + Group *n = s->group(View::GEOMETRY); + info << s->name() << ": "; + + // + // ALPHA + // + float v = s->alpha() * 100.f; + if (ImGuiToolkit::TextButton( ICON_FA_BULLSEYE , "Alpha")) { + s->call(new SetAlpha(1.f), true); + info << "Alpha " << std::fixed << std::setprecision(3) << 0.f; + Action::manager().store(info.str()); + } + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::SetNextItemWidth(sliderwidth); + if ( ImGui::DragFloat("##Alpha", &v, 0.1f, 0.f, 100.f, "%.1f%%") ) + s->call(new SetAlpha(v*0.01f), true); + if ( ImGui::IsItemDeactivatedAfterEdit() ) { + info << "Alpha " << std::fixed << std::setprecision(3) << v; + Action::manager().store(info.str()); + } + + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::Text("|"); + // + // POSITION COORDINATES + // + ImGui::SameLine(0, IMGUI_SAME_LINE); + if (ImGuiToolkit::TextButton( ICON_FA_SIGN, "Position")) { + n->translation_.x = 0.f; + n->translation_.y = 0.f; + s->touch(); + info << "Position " << std::setprecision(3) << n->translation_.x << ", " << n->translation_.y; + Action::manager().store(info.str()); + } + float vec[2] = { n->translation_.x * out.y * 0.5f, n->translation_.y * out.y * 0.5f}; + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::SetNextItemWidth( 2.f * sliderwidth); + if ( ImGui::DragFloat2("##Pos", vec, 1.0f, -MAX_SCALE * out.x, MAX_SCALE * out.x, "%.0fpx") ) { + n->translation_.x = vec[0] / (0.5f * out.y); + n->translation_.y = vec[1] / (0.5f * out.y); + s->touch(); + } + if ( ImGui::IsItemDeactivatedAfterEdit() ){ + info << "Position " << std::setprecision(3) << n->translation_.x << ", " << n->translation_.y; + Action::manager().store(info.str()); + } + + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::Text("|"); + + // + // SCALE + // + ImGui::SameLine(0, IMGUI_SAME_LINE); + if (ImGuiToolkit::TextButton( ICON_FA_RULER_COMBINED, "Size")) { + n->scale_.x = 1.f; + n->scale_.y = 1.f; + s->touch(); + info << "Scale " << std::setprecision(3) << n->scale_.x << ", " << n->scale_.y; + Action::manager().store(info.str()); + } + float ar_scale = n->scale_.x / n->scale_.y; + // SCALE X + v = n->scale_.x * ( out.y * s->frame()->aspectRatio()); + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::SetNextItemWidth( sliderwidth ); + if ( ImGui::DragFloat("##ScaleX", &v, 1.f, -MAX_SCALE * out.x, MAX_SCALE * out.x, "%.0fpx") ) { + if (v > 10.f) { + n->scale_.x = v / out.x; + if (*p_mode & SourceToolbar_linkar) + n->scale_.y = n->scale_.x / ar_scale; + s->touch(); + } + } + if ( ImGui::IsItemDeactivatedAfterEdit() ){ + info << "Scale " << std::setprecision(3) << n->scale_.x << " x " << n->scale_.y; + Action::manager().store(info.str()); + } + // SCALE LOCK ASPECT RATIO + ImGui::SameLine(0, 0); + bool lock = *p_mode & SourceToolbar_linkar; + if (ImGuiToolkit::IconToggle(5,1,6,1, &lock, tooltip_lock )) + *p_mode ^= SourceToolbar_linkar; // *p_mode |= lock ? SourceToolbar_linkar : !SourceToolbar_linkar; + ImGui::SameLine(0, 0); + // SCALE Y + v = n->scale_.y * out.y; + ImGui::SetNextItemWidth( sliderwidth ); + if ( ImGui::DragFloat("##ScaleY", &v, 1.f, -MAX_SCALE * out.y, MAX_SCALE * out.y, "%.0fpx") ) { + if (v > 10.f) { + n->scale_.y = v / out.y; + if (*p_mode & SourceToolbar_linkar) + n->scale_.x = n->scale_.y * ar_scale; + s->touch(); + } + } + if ( ImGui::IsItemDeactivatedAfterEdit() ){ + info << "Scale " << std::setprecision(3) << n->scale_.x << " x " << n->scale_.y; + Action::manager().store(info.str()); + } + + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::Text("|"); + + // + // ROTATION ANGLE + // + ImGui::SameLine(0, IMGUI_SAME_LINE); + if (ImGuiToolkit::IconButton( 18, 9, "Angle")) { + n->rotation_.z = 0.f; + s->touch(); + info << "Angle " << std::setprecision(3) << n->rotation_.z * 180.f / M_PI; + Action::manager().store(info.str()); + } + float v_deg = n->rotation_.z * 360.0f / (2.f*M_PI); + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::SetNextItemWidth(sliderwidth); + if ( ImGui::DragFloat("##Angle", &v_deg, 0.02f, -180.f, 180.f, "%.2f" UNICODE_DEGREE) ) { + n->rotation_.z = v_deg * (2.f*M_PI) / 360.0f; + s->touch(); + } + if ( ImGui::IsItemDeactivatedAfterEdit() ) { + info << "Angle " << std::setprecision(3) << n->rotation_.z * 180.f / M_PI; + Action::manager().store(info.str()); + } + + ImGui::SameLine(0, 2 * IMGUI_SAME_LINE); + + } + // NO SOURCE and not auto hide + else { + ImGui::AlignTextToFramePadding(); + ImGui::Text( MENU_SOURCE_TOOL ); + ImGui::SameLine(0, sliderwidth); + ImGui::TextDisabled("No source selected"); + ImGui::SameLine(0, sliderwidth); + } + + if (ImGuiToolkit::IconButton(5,8)) + ImGui::OpenPopup("sourcetool_menu"); + } + // + // compact layout for free placement + // + else { + ImGui::SetNextWindowPos(ImVec2(690,20), ImGuiCond_FirstUseEver); // initial pos + ImGui::SetNextWindowBgAlpha(WINDOW_TOOLBOX_ALPHA); // Transparent background + if (!ImGui::Begin("SourceToolbar", NULL, ImGuiWindowFlags_NoDecoration | + ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoNav)) + { + ImGui::End(); + return; + } + + // Title window + ImGui::Text( MENU_SOURCE_TOOL ); + ImGui::SameLine(0, 2.f * ImGui::GetTextLineHeightWithSpacing()); + if (ImGuiToolkit::IconButton(5,8)) + ImGui::OpenPopup("sourcetool_menu"); + + // WITH SOURCE + if (s) { + + // get info on source + Group *n = s->group(View::GEOMETRY); + info << s->name() << ": "; + + const float sliderwidth = 6.4f * ImGui::GetTextLineHeightWithSpacing(); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.f, 2.f)); + + // + // ALPHA + // + float v = s->alpha() * 100.f; + ImGui::SetNextItemWidth(sliderwidth); + if ( ImGui::DragFloat("##Alpha", &v, 0.1f, 0.f, 100.f, "%.1f%%") ) + s->call(new SetAlpha(v*0.01f), true); + if ( ImGui::IsItemDeactivatedAfterEdit() ) { + info << "Alpha " << std::fixed << std::setprecision(3) << v; + Action::manager().store(info.str()); + } + ImGui::SameLine(0, IMGUI_SAME_LINE); + if (ImGuiToolkit::TextButton("Alpha")) { + s->call(new SetAlpha(1.f), true); + info << "Alpha " << std::fixed << std::setprecision(3) << 0.f; + Action::manager().store(info.str()); + } + + // + // POSITION COORDINATES + // + float vec[2] = { n->translation_.x * out.y * 0.5f, n->translation_.y * out.y * 0.5f}; + ImGui::SetNextItemWidth(sliderwidth); + if ( ImGui::DragFloat2("##Pos", vec, 1.0f, -MAX_SCALE * out.x, MAX_SCALE * out.x, "%.0fpx") ) { + n->translation_.x = vec[0] / (0.5f * out.y); + n->translation_.y = vec[1] / (0.5f * out.y); + s->touch(); + } + if ( ImGui::IsItemDeactivatedAfterEdit() ){ + info << "Position " << std::setprecision(3) << n->translation_.x << ", " << n->translation_.y; + Action::manager().store(info.str()); + } + ImGui::SameLine(0, IMGUI_SAME_LINE); + if (ImGuiToolkit::TextButton("Pos")) { + n->translation_.x = 0.f; + n->translation_.y = 0.f; + s->touch(); + info << "Position " << std::setprecision(3) << n->translation_.x << ", " << n->translation_.y; + Action::manager().store(info.str()); + } + + // + // SCALE + // + float ar_scale = n->scale_.x / n->scale_.y; + // SCALE X + v = n->scale_.x * ( out.y * s->frame()->aspectRatio()); + ImGui::SetNextItemWidth( 2.7f * ImGui::GetTextLineHeightWithSpacing() ); + if ( ImGui::DragFloat("##ScaleX", &v, 1.f, -MAX_SCALE * out.x, MAX_SCALE * out.x, "%.0f") ) { + if (v > 10.f) { + n->scale_.x = v / out.x; + if (*p_mode & SourceToolbar_linkar) + n->scale_.y = n->scale_.x / ar_scale; + s->touch(); + } + } + if ( ImGui::IsItemDeactivatedAfterEdit() ){ + info << "Scale " << std::setprecision(3) << n->scale_.x << " x " << n->scale_.y; + Action::manager().store(info.str()); + } + // SCALE LOCK ASPECT RATIO + ImGui::SameLine(0, 0); + bool lock = *p_mode & SourceToolbar_linkar; + if (ImGuiToolkit::IconToggle(5,1,6,1, &lock, tooltip_lock )) + *p_mode ^= SourceToolbar_linkar; + ImGui::SameLine(0, 0); + // SCALE Y + v = n->scale_.y * out.y ; + ImGui::SetNextItemWidth( 2.7f * ImGui::GetTextLineHeightWithSpacing() ); + if ( ImGui::DragFloat("##ScaleY", &v, 1.f, -MAX_SCALE * out.y, MAX_SCALE * out.y, "%.0f") ) { + if (v > 10.f) { + n->scale_.y = v / out.y; + if (*p_mode & SourceToolbar_linkar) + n->scale_.x = n->scale_.y * ar_scale; + s->touch(); + } + } + if ( ImGui::IsItemDeactivatedAfterEdit() ){ + info << "Scale " << std::setprecision(3) << n->scale_.x << " x " << n->scale_.y; + Action::manager().store(info.str()); + } + ImGui::SameLine(0, IMGUI_SAME_LINE); + if (ImGuiToolkit::TextButton("Size")) { + n->scale_.x = 1.f; + n->scale_.y = 1.f; + s->touch(); + info << "Scale " << std::setprecision(3) << n->scale_.x << ", " << n->scale_.y; + Action::manager().store(info.str()); + } + + // + // ROTATION ANGLE + // + float v_deg = n->rotation_.z * 360.0f / (2.f*M_PI); + ImGui::SetNextItemWidth(sliderwidth); + if ( ImGui::DragFloat("##Angle", &v_deg, 0.02f, -180.f, 180.f, "%.2f" UNICODE_DEGREE) ) { + n->rotation_.z = v_deg * (2.f*M_PI) / 360.0f; + s->touch(); + } + if ( ImGui::IsItemDeactivatedAfterEdit() ) { + info << "Angle " << std::setprecision(3) << n->rotation_.z * 180.f / M_PI; + Action::manager().store(info.str()); + } + ImGui::SameLine(0, IMGUI_SAME_LINE); + if (ImGuiToolkit::TextButton("Angle")) { + n->rotation_.z = 0.f; + s->touch(); + info << "Angle " << std::setprecision(3) << n->rotation_.z * 180.f / M_PI; + Action::manager().store(info.str()); + } + + ImGui::PopStyleVar(); + } + // NO SOURCE and not auto hide + else { + + ImGui::TextDisabled(""); + ImGui::TextDisabled("No source selected"); + ImGui::TextDisabled(""); + + } + } + + if (ImGui::BeginPopup("sourcetool_menu")) + { + if (ImGui::MenuItem( "Auto hide", NULL, *p_mode & SourceToolbar_autohide)) + *p_mode ^= SourceToolbar_autohide; + + ImGui::Separator(); + + if (ImGui::MenuItem( ICON_FA_ANGLE_UP " Top", NULL, *p_border == 1)) + *p_border = 1; + if (ImGui::MenuItem( ICON_FA_ANGLE_DOWN " Bottom", NULL, *p_border == 3)) + *p_border = 3; + if (ImGui::MenuItem( ICON_FA_EXPAND_ARROWS_ALT " Free position", NULL, *p_border == -1)) + *p_border = -1; + if (p_open && ImGui::MenuItem( ICON_FA_TIMES " Close")) + *p_open = false; + + ImGui::EndPopup(); + } + + ImGui::Spacing(); + ImGui::End(); + } + +} + void UserInterface::RenderAbout(bool* p_open) { ImGui::SetNextWindowPos(ImVec2(1100, 20), ImGuiCond_FirstUseEver); @@ -2117,8 +2377,6 @@ void HelperToolbox::Render() ImGui::Text(ICON_FA_HAND_PAPER " " TOOLTIP_INPUTS "window"); ImGui::NextColumn(); ImGui::Text(SHORTCUT_SHADEREDITOR); ImGui::NextColumn(); ImGui::Text(ICON_FA_CODE " " TOOLTIP_SHADEREDITOR "window"); ImGui::NextColumn(); - ImGui::Text(SHORTCUT_NOTE); ImGui::NextColumn(); - ImGui::Text(MENU_NOTE); ImGui::NextColumn(); ImGui::Text("ESC"); ImGui::NextColumn(); ImGui::Text(ICON_FA_TOGGLE_OFF " Hide / " ICON_FA_TOGGLE_ON " Show windows"); ImGui::NextColumn(); ImGui::Separator(); @@ -8509,7 +8767,7 @@ void Navigator::RenderMainPannelVimix() ImGui::SameLine(0, ImGui::GetTextLineHeight()); static uint counter_menu_timeout = 0; - if ( ImGuiToolkit::IconButton( ICON_FA_SORT_DOWN ) || ImGui::IsItemHovered() ) { + if ( ImGuiToolkit::IconButton( ICON_FA_ELLIPSIS_V ) || ImGui::IsItemHovered() ) { counter_menu_timeout=0; ImGui::OpenPopup( "MenuToolboxWindows" ); } @@ -8518,14 +8776,17 @@ void Navigator::RenderMainPannelVimix() if (ImGui::BeginPopup( "MenuToolboxWindows" )) { - if (ImGui::MenuItem( MENU_NOTE, SHORTCUT_NOTE )) + // Enable / disable source toolbar + ImGui::MenuItem( MENU_SOURCE_TOOL, NULL, &Settings::application.widget.source_toolbar ); + // Enable / disable metrics toolbar + ImGui::MenuItem( MENU_METRICS, NULL, &Settings::application.widget.stats ); + // Add sticky note + if (ImGui::MenuItem( MENU_NOTE )) Mixer::manager().session()->addNote(); - - if ( ImGuiToolkit::MenuItemIcon( 11, 3, MENU_METRICS, SHORTCUT_METRICS, Settings::application.widget.stats ) ) - Settings::application.widget.stats = !Settings::application.widget.stats; - - ImGui::MenuItem( MENU_HELP, SHORTCUT_HELP, &Settings::application.widget.help ); - + // Show help + if (ImGui::MenuItem( MENU_HELP, SHORTCUT_HELP) ) + Settings::application.widget.help = true; + // timer to close menu like a tooltip if (ImGui::IsWindowHovered()) counter_menu_timeout=0; else if (++counter_menu_timeout > 60) diff --git a/src/UserInterfaceManager.h b/src/UserInterfaceManager.h index 11811a0..82a53b6 100644 --- a/src/UserInterfaceManager.h +++ b/src/UserInterfaceManager.h @@ -76,10 +76,9 @@ #define MENU_CLOSE ICON_FA_TIMES " Close" #define DIALOG_FAILED_SOURCE ICON_FA_EXCLAMATION_TRIANGLE " Source failure" -#define MENU_NOTE ICON_FA_STICKY_NOTE " New sticky note " -#define SHORTCUT_NOTE CTRL_MOD "Shift+N" -#define MENU_METRICS "Metrics" -#define SHORTCUT_METRICS CTRL_MOD "M" +#define MENU_NOTE ICON_FA_STICKY_NOTE " Add sticky note" +#define MENU_METRICS ICON_FA_TACHOMETER_ALT " Metrics" +#define MENU_SOURCE_TOOL ICON_FA_VECTOR_SQUARE " Source editor" #define MENU_HELP ICON_FA_LIFE_RING " Help" #define SHORTCUT_HELP CTRL_MOD "H" #define TOOLTIP_PLAYER "Player " @@ -102,6 +101,11 @@ #define TOOLTIP_SHOW "Show windows " #define SHORTCUT_HIDE "ESC" +#define LABEL_AUTO_MEDIA_PLAYER ICON_FA_USER_CIRCLE " User selection" +#define LABEL_STORE_SELECTION " Create batch" +#define LABEL_EDIT_FADING ICON_FA_RANDOM " Fade in & out" +#define LABEL_VIDEO_SEQUENCE " Encode an image sequence" + #include "SourceList.h" #include "InfoVisitor.h" #include "DialogToolkit.h" @@ -522,6 +526,7 @@ protected: void selectOpenFilename(); void RenderMetrics (bool* p_open, int* p_corner, int *p_mode); + void RenderSourceToolbar(bool *p_open, int* p_border, int *p_mode); int RenderViewNavigator(int* shift); void RenderOutputView(); void RenderAbout(bool* p_open);