From d6a684bbe7f763543ea4d233ad8ae44651cabb56 Mon Sep 17 00:00:00 2001 From: Bruno Herbelin Date: Mon, 3 Jul 2023 20:50:48 +0200 Subject: [PATCH] Improved behavior left panel New behavior left panel depending on settings of always_visible panel. Remembers (access from UserInterface) the source that is currently selected in the left panel, and use this source as the one manipulated in TextureView. List possible source new source modes with large icons (instead of combo box). --- src/TextureView.cpp | 20 +-- src/UserInterfaceManager.cpp | 229 +++++++++++++++++++++++++---------- src/UserInterfaceManager.h | 4 + 3 files changed, 178 insertions(+), 75 deletions(-) diff --git a/src/TextureView.cpp b/src/TextureView.cpp index 66d1ba0..27418f2 100644 --- a/src/TextureView.cpp +++ b/src/TextureView.cpp @@ -488,17 +488,17 @@ Source *TextureView::getEditOrCurrentSource() // get current source Source *_source = Mixer::manager().currentSource(); - // no current source? - if (_source == nullptr) { - // if something can be selected - if ( !Mixer::manager().session()->empty()) { - // return the edit source, if exists - if (edit_source_ != nullptr) { - _source = Mixer::manager().findSource(edit_source_->id()); - // put the edit source back in the selection - Mixer::selection().set(_source); - } + // no current source but possible source + if (_source == nullptr && Mixer::manager().numSource() > 0) { + // then get the source active in user interface left panel + _source = UserInterface::manager().sourceInPanel(); + // no source in panel neither? + if (_source == nullptr && edit_source_ != nullptr) { + // then keep the current edit source ( if still available ) + _source = Mixer::manager().findSource( edit_source_->id() ); } + // ensures the source is selected + Mixer::selection().set(_source); } // do not work on a failed source diff --git a/src/UserInterfaceManager.cpp b/src/UserInterfaceManager.cpp index 03ce029..679a048 100644 --- a/src/UserInterfaceManager.cpp +++ b/src/UserInterfaceManager.cpp @@ -235,6 +235,12 @@ uint64_t UserInterface::Runtime() const } +void UserInterface::setView(View::Mode mode) +{ + Mixer::manager().setView(mode); + navigator.hidePannel(); +} + void UserInterface::handleKeyboard() { static bool esc_repeat_ = false; @@ -357,15 +363,15 @@ void UserInterface::handleKeyboard() // Application F-Keys if (ImGui::IsKeyPressed( GLFW_KEY_F1, false )) - Mixer::manager().setView(View::MIXING); + setView(View::MIXING); else if (ImGui::IsKeyPressed( GLFW_KEY_F2, false )) - Mixer::manager().setView(View::GEOMETRY); + setView(View::GEOMETRY); else if (ImGui::IsKeyPressed( GLFW_KEY_F3, false )) - Mixer::manager().setView(View::LAYER); + setView(View::LAYER); else if (ImGui::IsKeyPressed( GLFW_KEY_F4, false )) - Mixer::manager().setView(View::TEXTURE); + setView(View::TEXTURE); else if (ImGui::IsKeyPressed( GLFW_KEY_F5, false )) - Mixer::manager().setView(View::DISPLAYS); + setView(View::DISPLAYS); else if (ImGui::IsKeyPressed( GLFW_KEY_F9, false )) StartScreenshot(); else if (ImGui::IsKeyPressed( GLFW_KEY_F10, false )) @@ -585,13 +591,7 @@ void UserInterface::handleMouse() { // if double clic action of view didn't succeed if ( !Mixer::manager().view()->doubleclic(mousepos) ) { - // default behavior : - if (navigator.pannelVisible()) - // discard current to select front most source - // (because single clic maintains same source active) - Mixer::manager().unsetCurrentSource(); - - // display source in left pannel + // display current source in left panel /or/ hide left panel if no current source navigator.showPannelSource( Mixer::manager().indexCurrentSource() ); } } @@ -672,8 +672,10 @@ void UserInterface::handleMouse() if ( ImGui::IsMouseReleased(ImGuiMouseButton_Left) || ImGui::IsMouseReleased(ImGuiMouseButton_Right) ) { // special case of one single source in area selection : make current after release - if (view_drag && picked.first == nullptr && Mixer::selection().size() == 1) + if (view_drag && picked.first == nullptr && Mixer::selection().size() == 1) { Mixer::manager().setCurrentSource( Mixer::selection().front() ); + navigator.hidePannel(); + } view_drag = nullptr; mousedown = false; @@ -1119,32 +1121,32 @@ int UserInterface::RenderViewNavigator(int *shift) ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE); if (ImGui::Selectable( ICON_FA_BULLSEYE, &selected_view[1], 0, iconsize)) { - Mixer::manager().setView(View::MIXING); + setView(View::MIXING); *shift = 0; } ImGui::NextColumn(); if (ImGui::Selectable( ICON_FA_OBJECT_UNGROUP , &selected_view[2], 0, iconsize)) { - Mixer::manager().setView(View::GEOMETRY); + setView(View::GEOMETRY); *shift = 0; } ImGui::NextColumn(); if (ImGui::Selectable( ICON_FA_LAYER_GROUP, &selected_view[3], 0, iconsize)) { - Mixer::manager().setView(View::LAYER); + setView(View::LAYER); *shift = 0; } ImGui::NextColumn(); if (ImGui::Selectable( ICON_FA_CHESS_BOARD, &selected_view[4], 0, iconsize)) { - Mixer::manager().setView(View::TEXTURE); + setView(View::TEXTURE); *shift = 0; } // skip TRANSITION view ImGui::NextColumn(); if (ImGui::Selectable( ICON_FA_TV, &selected_view[6], 0, iconsize)) { - Mixer::manager().setView(View::DISPLAYS); + setView(View::DISPLAYS); *shift = 0; } ImGui::PopFont(); @@ -1178,6 +1180,18 @@ void UserInterface::showSourcePanel(Source *s) } } +Source *UserInterface::sourceInPanel() +{ + Source *ret = nullptr; + + int idxpanel = navigator.selectedPannelSource(); + if (idxpanel > -1 && idxpanel < NAV_MAX) { + ret = Mixer::manager().sourceAtIndex(idxpanel); + } + + return ret; +} + void UserInterface::showSourceEditor(Source *s) { Mixer::manager().unsetCurrentSource(); @@ -7229,6 +7243,7 @@ void Navigator::applyButtonSelection(int index) bool status = selected_button[index]; clearButtonSelection(); selected_button[index] = status; + selected_index = index; // set visible if button is active pannel_visible_ = status; @@ -7256,10 +7271,12 @@ void Navigator::clearButtonSelection() // clear new source pannel clearNewPannel(); source_to_replace = nullptr; + selected_index = -1; } void Navigator::showPannelSource(int index) { + selected_index = index; // invalid index given if ( index < 0 ) hidePannel(); @@ -7269,6 +7286,11 @@ void Navigator::showPannelSource(int index) } } +int Navigator::selectedPannelSource() +{ + return selected_index; +} + void Navigator::showConfig() { selected_button[NAV_MENU] = true; @@ -7280,6 +7302,9 @@ void Navigator::togglePannelMenu() { selected_button[NAV_MENU] = !selected_button[NAV_MENU]; applyButtonSelection(NAV_MENU); + + if (Settings::application.pannel_always_visible) + showPannelSource(NAV_MENU); } void Navigator::togglePannelNew() @@ -7303,23 +7328,46 @@ void Navigator::togglePannelAutoHide() else showPannelSource( current ); } - else + else { + pannel_visible_ = true; hidePannel(); + } } bool Navigator::pannelVisible() { - return pannel_visible_; + return pannel_visible_ || Settings::application.pannel_always_visible; } void Navigator::hidePannel() { - if ( Settings::application.pannel_always_visible ) - showPannelSource(NAV_MENU); - else if ( pannel_visible_) { - clearButtonSelection(); - pannel_visible_ = false; + if ( Settings::application.pannel_always_visible ) { + + if ( !selected_button[NAV_MENU] && !selected_button[NAV_TRANS] && !selected_button[NAV_NEW] ) + { + // get index of current source + int idx = Mixer::manager().indexCurrentSource(); + if (idx < 0) { + // no current source, try to get source previously in panel + Source *cs = Mixer::manager().sourceAtIndex( selected_index ); + if ( cs ) + idx = selected_index; + else { + // really no source is current, try to get one from user selection + cs = Mixer::selection().front(); + if ( cs ) + idx = Mixer::manager().session()->index( Mixer::manager().session()->find(cs) ); + } + } + // if current source or a selected source, show it's pannel + if (idx >= 0) + showPannelSource( idx ); + } } + else if ( pannel_visible_) + clearButtonSelection(); + + pannel_visible_ = false; view_pannel_visible = false; show_config_ = false; } @@ -7367,6 +7415,14 @@ void Navigator::Render() if (ImGui::IsItemHovered()) tooltip = {TOOLTIP_MAIN, SHORTCUT_MAIN}; + // the "+" icon for action of creating new source + if (ImGui::Selectable( source_to_replace != nullptr ? ICON_FA_PLUS_SQUARE : ICON_FA_PLUS, + &selected_button[NAV_NEW], 0, iconsize)) { + Mixer::manager().unsetCurrentSource(); + applyButtonSelection(NAV_NEW); + } + if (ImGui::IsItemHovered()) + tooltip = {TOOLTIP_NEW_SOURCE, SHORTCUT_NEW_SOURCE}; // // the list of INITIALS for sources // @@ -7433,14 +7489,6 @@ void Navigator::Render() ImGui::PopID(); } - // the "+" icon for action of creating new source - if (ImGui::Selectable( source_to_replace != nullptr ? ICON_FA_PLUS_SQUARE : ICON_FA_PLUS, - &selected_button[NAV_NEW], 0, iconsize)) { - Mixer::manager().unsetCurrentSource(); - applyButtonSelection(NAV_NEW); - } - if (ImGui::IsItemHovered()) - tooltip = {TOOLTIP_NEW_SOURCE, SHORTCUT_NEW_SOURCE}; } else { // the ">" icon for transition menu @@ -7465,35 +7513,35 @@ void Navigator::Render() int previous_view = Settings::application.current_view; if (ImGui::Selectable( ICON_FA_BULLSEYE, &selected_view[View::MIXING], 0, iconsize)) { - Mixer::manager().setView(View::MIXING); + UserInterface::manager().setView(View::MIXING); view_pannel_visible = previous_view == Settings::application.current_view; } if (ImGui::IsItemHovered()) tooltip = {"Mixing ", "F1"}; if (ImGui::Selectable( ICON_FA_OBJECT_UNGROUP , &selected_view[View::GEOMETRY], 0, iconsize)) { - Mixer::manager().setView(View::GEOMETRY); + UserInterface::manager().setView(View::GEOMETRY); view_pannel_visible = previous_view == Settings::application.current_view; } if (ImGui::IsItemHovered()) tooltip = {"Geometry ", "F2"}; if (ImGui::Selectable( ICON_FA_LAYER_GROUP, &selected_view[View::LAYER], 0, iconsize)) { - Mixer::manager().setView(View::LAYER); + UserInterface::manager().setView(View::LAYER); view_pannel_visible = previous_view == Settings::application.current_view; } if (ImGui::IsItemHovered()) tooltip = {"Layers ", "F3"}; if (ImGui::Selectable( ICON_FA_CHESS_BOARD, &selected_view[View::TEXTURE], 0, iconsize)) { - Mixer::manager().setView(View::TEXTURE); + UserInterface::manager().setView(View::TEXTURE); view_pannel_visible = previous_view == Settings::application.current_view; } if (ImGui::IsItemHovered()) tooltip = {"Texturing ", "F4"}; if (ImGui::Selectable( ICON_FA_TV, &selected_view[View::DISPLAYS], 0, iconsize)) { - Mixer::manager().setView(View::DISPLAYS); + UserInterface::manager().setView(View::DISPLAYS); view_pannel_visible = previous_view == Settings::application.current_view; } if (ImGui::IsItemHovered()) @@ -7539,9 +7587,15 @@ void Navigator::Render() ImGui::PopFont(); // Rendering of the side pannel - if ( pannel_visible_ || Settings::application.pannel_always_visible ){ + if ( Settings::application.pannel_always_visible || pannel_visible_ ){ - pannel_alpha_ = Settings::application.pannel_always_visible ? 0.95f : 0.85f; + // slight differences if temporari vixible or always visible panel + if (Settings::application.pannel_always_visible) + pannel_alpha_ = 0.95f; + else { + pannel_alpha_ = 0.85f; + view_pannel_visible = false; + } // pannel menu if (selected_button[NAV_MENU]) @@ -7561,10 +7615,20 @@ void Navigator::Render() // pannel to configure a selected source else { - RenderSourcePannel(Mixer::manager().currentSource()); + if ( selected_index < 0 ) + showPannelSource(NAV_MENU); + // most often, render current sources + else if ( selected_index == Mixer::manager().indexCurrentSource()) + RenderSourcePannel(Mixer::manager().currentSource()); + // rarely its not the current source that is selected + else { + SourceList::iterator cs = Mixer::manager().session()->at( selected_index ); + if (cs != Mixer::manager().session()->end() ) + RenderSourcePannel( *cs ); + } } - view_pannel_visible = false; } + ImGui::PopStyleColor(2); ImGui::PopStyleVar(); @@ -7575,7 +7639,7 @@ void Navigator::RenderViewPannel(ImVec2 draw_pos , ImVec2 draw_size) ImGui::SetNextWindowPos( draw_pos, ImGuiCond_Always ); ImGui::SetNextWindowSize( draw_size, ImGuiCond_Always ); ImGui::SetNextWindowBgAlpha(0.95f); // Transparent background - if (ImGui::Begin("##ViewPannel", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) + if (ImGui::Begin("##ViewPannel", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNav)) { ImGui::SetCursorPosX(10.f); ImGui::SetCursorPosY(10.f); @@ -7725,6 +7789,10 @@ void Navigator::RenderNewPannel() if (Settings::application.current_view == View::TRANSITION) return; + const ImGuiStyle& style = ImGui::GetStyle(); + const float icon_width = width_ - 2.f * style.WindowPadding.x; + const ImVec2 iconsize(icon_width, icon_width); + // Next window is a side pannel ImGui::SetNextWindowPos( ImVec2(width_, 0), ImGuiCond_Always ); ImGui::SetNextWindowSize( ImVec2(pannel_width_, height_), ImGuiCond_Always ); @@ -7738,26 +7806,47 @@ void Navigator::RenderNewPannel() ImGui::Text("Replace"); else ImGui::Text("Insert"); - ImGui::PopFont(); - - // Edit menu - ImGui::SetCursorPosY(width_); - ImGui::Text("Source"); // // News Source selection pannel // - static const char* origin_names[SOURCE_TYPES] = { ICON_FA_PHOTO_VIDEO " File", - ICON_FA_IMAGES " Sequence", - ICON_FA_PLUG " Connected", - ICON_FA_COG " Generated", - ICON_FA_SYNC " Internal" - }; - ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - if (ImGui::Combo("##Origin", &Settings::application.source.new_type, origin_names, IM_ARRAYSIZE(origin_names)) ) - clearNewPannel(); + ImGui::SetCursorPosY(width_ - style.WindowPadding.x); + ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.5f, 0.5f)); - ImGui::SetCursorPosY(2.f * width_); + ImGui::Columns(5, NULL, false); + bool selected_type[5] = {0}; + selected_type[Settings::application.source.new_type] = true; + if (ImGui::Selectable( ICON_FA_PHOTO_VIDEO, &selected_type[SOURCE_FILE], 0, iconsize)) { + Settings::application.source.new_type = SOURCE_FILE; + clearNewPannel(); + } + ImGui::NextColumn(); + if (ImGui::Selectable( ICON_FA_IMAGES, &selected_type[SOURCE_SEQUENCE], 0, iconsize)) { + Settings::application.source.new_type = SOURCE_SEQUENCE; + clearNewPannel(); + } + ImGui::NextColumn(); + if (ImGui::Selectable( ICON_FA_PLUG, &selected_type[SOURCE_CONNECTED], 0, iconsize)) { + Settings::application.source.new_type = SOURCE_CONNECTED; + clearNewPannel(); + } + ImGui::NextColumn(); + if (ImGui::Selectable( ICON_FA_COGS, &selected_type[SOURCE_GENERATED], 0, iconsize)) { + Settings::application.source.new_type = SOURCE_GENERATED; + clearNewPannel(); + } + ImGui::NextColumn(); + if (ImGui::Selectable( ICON_FA_RETWEET, &selected_type[SOURCE_INTERNAL], 0, iconsize)) { + Settings::application.source.new_type = SOURCE_INTERNAL; + clearNewPannel(); + } + + ImGui::Columns(1); + ImGui::PopStyleVar(); + ImGui::PopFont(); + + // Edit menu + ImGui::SetCursorPosY(width_ * 1.9f); // File Source creation if (Settings::application.source.new_type == SOURCE_FILE) { @@ -7765,8 +7854,10 @@ void Navigator::RenderNewPannel() static DialogToolkit::OpenMediaDialog fileimportdialog("Open Media"); static DialogToolkit::OpenFolderDialog folderimportdialog("Select Folder"); + ImGui::Text("Load media file:"); + // clic button to load file - if ( ImGui::Button( ICON_FA_FOLDER_OPEN " Open File", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) ) + if ( ImGui::Button( ICON_FA_FOLDER_OPEN " Open", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) ) fileimportdialog.open(); // Indication ImGui::SameLine(); @@ -7963,8 +8054,10 @@ void Navigator::RenderNewPannel() static MultiFileRecorder _video_recorder; static int _fps = 25; + ImGui::Text("Create image sequence:"); + // clic button to load file - if ( ImGui::Button( ICON_FA_FOLDER_OPEN " Open images", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) ) { + if ( ImGui::Button( ICON_FA_FOLDER_OPEN " Open multiple", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) ) { sourceSequenceFiles.clear(); new_source_preview_.setSource(); _selectImagesDialog.open(); @@ -7998,7 +8091,7 @@ void Navigator::RenderNewPannel() // multiple files selected if (sourceSequenceFiles.size() > 1) { - ImGui::Text("\nCreate image sequence:"); + ImGui::Text(" "); // show info sequence ImGuiTextBuffer info; @@ -8097,9 +8190,11 @@ void Navigator::RenderNewPannel() // Internal Source creator else if (Settings::application.source.new_type == SOURCE_INTERNAL){ + ImGui::Text("Loopback object:"); + // fill new_source_preview with a new source ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - if (ImGui::BeginCombo("##Source", "Select object")) + if (ImGui::BeginCombo("##Source", "Select")) { std::string label = "Rendering Loopback"; if (ImGui::Selectable( label.c_str() )) { @@ -8128,8 +8223,10 @@ void Navigator::RenderNewPannel() bool update_new_source = false; + ImGui::Text("Generate graphics:"); + ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - if (ImGui::BeginCombo("##Pattern", "Select generator", ImGuiComboFlags_HeightLarge)) + if (ImGui::BeginCombo("##Pattern", "Select", ImGuiComboFlags_HeightLarge)) { if ( ImGui::Selectable("Custom " ICON_FA_CARET_RIGHT) ) { update_new_source = true; @@ -8215,8 +8312,10 @@ void Navigator::RenderNewPannel() // External source creator else if (Settings::application.source.new_type == SOURCE_CONNECTED){ + ImGui::Text("Connect device or stream:"); + ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - if (ImGui::BeginCombo("##External", "Select stream")) + if (ImGui::BeginCombo("##External", "Select ")) { for (int d = 0; d < Device::manager().numDevices(); ++d){ std::string namedev = Device::manager().name(d); @@ -9402,7 +9501,7 @@ void Navigator::RenderTransitionPannel() if (tv) tv->play(true); } if ( ImGui::Button( ICON_FA_DOOR_OPEN " Exit", ImVec2(ImGui::GetContentRegionAvail().x, 0)) ) - Mixer::manager().setView(View::MIXING); + UserInterface::manager().setView(View::MIXING); ImGui::End(); } diff --git a/src/UserInterfaceManager.h b/src/UserInterfaceManager.h index e77a287..bfcf290 100644 --- a/src/UserInterfaceManager.h +++ b/src/UserInterfaceManager.h @@ -175,6 +175,7 @@ class Navigator float pannel_alpha_; bool view_pannel_visible; bool selected_button[NAV_COUNT]; + int selected_index; int pattern_type; bool custom_pipeline; bool custom_connected; @@ -208,6 +209,7 @@ public: bool pannelVisible(); void hidePannel(); void showPannelSource(int index); + int selectedPannelSource(); void togglePannelMenu(); void togglePannelNew(); void showConfig(); @@ -491,6 +493,7 @@ public: void showPannel(int id = 0); void showSourcePanel(Source *s); + Source *sourceInPanel(); void showSourceEditor(Source *s); void StartScreenshot(); @@ -542,6 +545,7 @@ protected: void RenderAbout(bool* p_open); void RenderNotes(); + void setView(View::Mode mode); void handleKeyboard(); void handleMouse(); void handleScreenshot();