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);