From 614fa1247d9fbcfbe67f79a88cc7ec8a06356016 Mon Sep 17 00:00:00 2001 From: brunoherbelin Date: Sat, 23 May 2020 19:13:05 +0200 Subject: [PATCH] Improved creation of source: selection of file generates a new source, displayed in preview, and inserted when validated. --- ImGuiToolkit.cpp | 5 ++ ImGuiToolkit.h | 1 - ImGuiVisitor.cpp | 2 - Mixer.cpp | 13 ++++ Mixer.h | 1 + Source.cpp | 15 ++-- Source.h | 5 +- UserInterfaceManager.cpp | 162 +++++++++++++++++++++++---------------- UserInterfaceManager.h | 18 ++++- 9 files changed, 146 insertions(+), 76 deletions(-) diff --git a/ImGuiToolkit.cpp b/ImGuiToolkit.cpp index 6a8dccb..16dd97e 100644 --- a/ImGuiToolkit.cpp +++ b/ImGuiToolkit.cpp @@ -792,6 +792,11 @@ ImVec4 ImGuiToolkit::GetHighlightColor() void ImGuiToolkit::SetAccentColor(accent_color color) { + // hack : preload texture icon to prevent slow-down of rendering when creating a new icon for the first time + if (textureicons == 0) + textureicons = Resource::getTextureDDS("images/icons.dds"); + + ImVec4* colors = ImGui::GetStyle().Colors; if (color == ImGuiToolkit::ACCENT_ORANGE) { diff --git a/ImGuiToolkit.h b/ImGuiToolkit.h index f40681c..e1c3cd1 100644 --- a/ImGuiToolkit.h +++ b/ImGuiToolkit.h @@ -10,7 +10,6 @@ namespace ImGuiToolkit { - // Icons from resource icon.dds void Icon(int i, int j); void ShowIconsWindow(bool* p_open); diff --git a/ImGuiVisitor.cpp b/ImGuiVisitor.cpp index 731f0b6..576a4a6 100644 --- a/ImGuiVisitor.cpp +++ b/ImGuiVisitor.cpp @@ -265,8 +265,6 @@ void ImGuiVisitor::visit (Source& s) // geometry direct control s.groupNode(View::GEOMETRY)->accept(*this); - // Action on source -// ImGui::Button("Clone", ImVec2(IMGUI_RIGHT_ALIGN, 0)); } void ImGuiVisitor::visit (MediaSource& s) diff --git a/Mixer.cpp b/Mixer.cpp index 8f8e691..1331e66 100644 --- a/Mixer.cpp +++ b/Mixer.cpp @@ -258,7 +258,10 @@ void Mixer::insertSource(Source *s) geometry_.scene.ws()->attach(s->group(View::GEOMETRY)); layer_.scene.ws()->attach(s->group(View::LAYER)); + // set a default depth to the new source layer_.setDepth(s); + + current_view_->update(0); } } @@ -357,6 +360,16 @@ void Mixer::unsetCurrentSource() current_source_index_ = -1; } +void Mixer::cloneCurrentSource() +{ + if ( current_source_ != session_->end() ) + { + Source *s = createSourceClone( (*current_source_)->name() ); + + insertSource(s); + } +} + int Mixer::indexCurrentSource() { return current_source_index_; diff --git a/Mixer.h b/Mixer.h index 4b8a71e..4ce5f8d 100644 --- a/Mixer.h +++ b/Mixer.h @@ -49,6 +49,7 @@ public: void setCurrentSource(int index); void setCurrentSource(Source *s); void unsetCurrentSource(); + void cloneCurrentSource(); void deleteCurrentSource(); Source * currentSource(); int indexCurrentSource(); diff --git a/Source.cpp b/Source.cpp index 48b1390..d458213 100644 --- a/Source.cpp +++ b/Source.cpp @@ -136,6 +136,15 @@ void Source::setOverlayVisible(bool on) (*o).second->visible_ = on; } +void Source::setVisible(bool on) +{ + // make visible + groups_[View::RENDERING]->visible_ = on; + groups_[View::MIXING]->visible_ = on; + groups_[View::GEOMETRY]->visible_ = on; + groups_[View::LAYER]->visible_ = on; +} + void Source::attach(FrameBuffer *renderbuffer) { renderbuffer_ = renderbuffer; @@ -169,11 +178,7 @@ void Source::attach(FrameBuffer *renderbuffer) (*node)->scale_.x = renderbuffer_->aspectRatio(); } - // make visible - groups_[View::RENDERING]->visible_ = true; - groups_[View::MIXING]->visible_ = true; - groups_[View::GEOMETRY]->visible_ = true; - groups_[View::LAYER]->visible_ = true; + setVisible(true); } void Source::update(float dt) diff --git a/Source.h b/Source.h index 4852d3c..dfe2238 100644 --- a/Source.h +++ b/Source.h @@ -38,8 +38,11 @@ public: // cloning mechanism virtual CloneSource *clone(); + // make visible or hidden + void setVisible(bool on); + // an overlay can be displayed on top of the source - virtual void setOverlayVisible(bool on); + void setOverlayVisible(bool on); // get handle on the node used to manipulate the source in a view inline Group *group(View::Mode m) const { return groups_.at(m); } diff --git a/UserInterfaceManager.cpp b/UserInterfaceManager.cpp index b5fb5bd..2faa686 100644 --- a/UserInterfaceManager.cpp +++ b/UserInterfaceManager.cpp @@ -105,7 +105,7 @@ static void SessionFileDialogSave(std::string path) sessionFileDialogSaveFinished_ = true; } -static void ImportFileDialogOpen(char *filename, const std::string &path) +static void ImportFileDialogOpen(char *filename, std::atomic *success, const std::string &path) { if (fileDialogPending_) return; @@ -115,7 +115,14 @@ static void ImportFileDialogOpen(char *filename, const std::string &path) char const * open_file_name; open_file_name = tinyfd_openFileDialog( "Import a file", path.c_str(), 18, open_pattern, "All supported formats", 0); - sprintf(filename, "%s", open_file_name); + + if (open_file_name) { + sprintf(filename, "%s", open_file_name); + *success = true; + } + else { + *success = false; + } fileDialogPending_ = false; } @@ -855,7 +862,6 @@ Navigator::Navigator() height = 100; padding_width = 100; new_source_type_ = 0; - new_source_to_create_ = ""; sprintf(new_source_filename_, " "); } @@ -874,8 +880,9 @@ void Navigator::clearSelection() { for(int i=0; itouch(); // delete button ImGui::Text(" "); + // Action on source + if ( ImGui::Button("Clone", ImVec2(ImGui::GetContentRegionAvail().x, 0)) ) + Mixer::manager().cloneCurrentSource(); if ( ImGui::Button("Delete", ImVec2(ImGui::GetContentRegionAvail().x, 0)) ) { Mixer::manager().deleteSource(s); } @@ -1061,6 +1071,45 @@ void Navigator::RenderSourcePannel(Source *s) } +SourcePreview::SourcePreview() : source_(nullptr), label_("") +{ + +} + +void SourcePreview::setSource(Source *s, std::string label) +{ + if(source_) + delete source_; + + source_ = s; + label_ = label; +} + +Source * SourcePreview::getSource() +{ + Source *s = source_; + source_ = nullptr; + return s; +} + +void SourcePreview::draw(float width) +{ + if(source_) { + // cancel if failed + if (source_->failed()) + setSource(); + else + { + // render framebuffer + source_->render(); + // draw preview + ImVec2 preview_size(width, width / source_->frame()->aspectRatio()); + ImGui::Image((void*)(uintptr_t) source_->frame()->texture(), preview_size); + ImGui::Text("%s ", label_.c_str()); + } + } +} + void Navigator::RenderNewPannel() { // Next window is a side pannel @@ -1078,108 +1127,89 @@ void Navigator::RenderNewPannel() ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); ImGui::Combo("Origin", &new_source_type_, "File\0Software\0Hardware\0"); - // Media Source creation + // File Source creation if (new_source_type_ == 0) { + // helper ImGui::SetCursorPosX(pannel_width - 30 + IMGUI_RIGHT_ALIGN); ImGuiToolkit::HelpMarker("Create a source from a file:\n- Video (*.mpg, *mov, *.avi, etc.)\n- Image (*.jpg, *.png, etc.)\n- Vector graphics (*.svg)\n- vimix session (*.vmx)\n\nEquivalent to dropping the file in the workspace."); // browse for a filename - if (ImGuiToolkit::ButtonIcon(2, 5)) { - std::thread (ImportFileDialogOpen, new_source_filename_, Settings::application.recentImport.path).detach(); + static std::atomic file_selected = false; + if ( ImGui::Button( ICON_FA_FILE_IMPORT " Open", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) ) { + // clear string before selection + file_selected = false; + std::thread (ImportFileDialogOpen, new_source_filename_, &file_selected, Settings::application.recentImport.path).detach(); } + if ( file_selected ) { + file_selected = false; + std::string open_filename(new_source_filename_); + // create a source with this file + std::string label = open_filename.substr( open_filename.size() - MIN( 35, open_filename.size()) ); + new_source_preview_.setSource( Mixer::manager().createSourceFile(open_filename), label); + } + // combo of recent media filenames - ImGui::SameLine(0, 10); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); if (ImGui::BeginCombo("##RecentImport", "Select recent")) { for (auto path = Settings::application.recentImport.filenames.begin(); path != Settings::application.recentImport.filenames.end(); path++ ) { - int right = MIN( 40, path->size()); - if (ImGui::Selectable( path->substr( path->size() - right ).c_str() )) { - sprintf(new_source_filename_, "%s", path->c_str()); + std::string label = path->substr( path->size() - MIN( 35, path->size()) ); + if (ImGui::Selectable( label.c_str() )) { + new_source_preview_.setSource( Mixer::manager().createSourceFile(path->c_str()), label); } } ImGui::EndCombo(); } - // filename text entry - [Return] to validate - ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - Source *s = nullptr; - if (ImGui::InputText("Path", new_source_filename_, IM_ARRAYSIZE(new_source_filename_), ImGuiInputTextFlags_EnterReturnsTrue) ) { - s = Mixer::manager().createSourceFile( std::string(new_source_filename_) ); - selected_button[NAV_NEW] = false; + // if a new source was added + if (new_source_preview_.ready()) { + // show preview + new_source_preview_.draw(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); + // or press Validate button + if ( ImGui::Button("Import", ImVec2(pannel_width - padding_width, 0)) ) { + Mixer::manager().insertSource(new_source_preview_.getSource()); + selected_button[NAV_NEW] = false; + } } - // or press Validate button - ImGui::Text(" "); - if ( ImGui::Button("Create !", ImVec2(pannel_width - padding_width, 0)) ) { - s = Mixer::manager().createSourceFile( std::string(new_source_filename_) ); - selected_button[NAV_NEW] = false; - } - Mixer::manager().insertSource(s); } - // Render Source creator + // Software Source creator else if (new_source_type_ == 1){ // helper ImGui::SetCursorPosX(pannel_width - 30 + IMGUI_RIGHT_ALIGN); ImGuiToolkit::HelpMarker("Create a source from a software algorithm or from vimix objects."); - // Selection of a source to create - static uint texture = 0; - static ImVec2 preview_size; - static ImVec2 preview_uv1, preview_uv2; - static float preview_width = ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; - + // fill new_source_preview with a new source ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - if (ImGui::BeginCombo("##Source", "Select source")) + if (ImGui::BeginCombo("##Source", "Select input")) { - if (ImGui::Selectable( "Render" )) { - new_source_to_create_ = "Render"; - texture = Mixer::manager().session()->frame()->texture(); - preview_size = ImVec2( preview_width, preview_width / Mixer::manager().session()->frame()->aspectRatio()); - preview_uv1 = ImVec2(0.f, 1.f); - preview_uv2 = ImVec2(1.f, 0.f); + std::string label = "Rendering output"; + if (ImGui::Selectable( label.c_str() )) { + new_source_preview_.setSource( Mixer::manager().createSourceRender(), label); } SourceList::iterator iter; for (iter = Mixer::manager().session()->begin(); iter != Mixer::manager().session()->end(); iter++) { - if (ImGui::Selectable( (*iter)->name().c_str() )) { - new_source_to_create_ = (*iter)->name(); - texture = (*iter)->texture(); - preview_size = ImVec2( preview_width, preview_width / (*iter)->frame()->aspectRatio()); - preview_uv1 = ImVec2(0.f, 0.f); - preview_uv2 = ImVec2(1.f, 1.f); + label = std::string("Clone of ") + (*iter)->name(); + if (ImGui::Selectable( label.c_str() )) { + new_source_preview_.setSource( Mixer::manager().createSourceClone((*iter)->name()),label); } } ImGui::EndCombo(); } - - if (!new_source_to_create_.empty()) { - - // preview - if (texture != 0) { - ImGui::Image((void*)(uintptr_t) texture, preview_size, preview_uv1, preview_uv2); - } - - ImGui::Text("%s ", new_source_to_create_.c_str()); - if ( ImGui::Button("Create !", ImVec2(pannel_width - padding_width, 0)) ) { - - Source *s = nullptr; - if (new_source_to_create_ == "Render") - s = Mixer::manager().createSourceRender(); - else - s = Mixer::manager().createSourceClone(new_source_to_create_); - - Mixer::manager().insertSource(s); - + // if a new source was added + if (new_source_preview_.ready()) { + // show preview + new_source_preview_.draw(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); + // ask to import the source in the mixer + if ( ImGui::Button("Import", ImVec2(pannel_width - padding_width, 0)) ) { + Mixer::manager().insertSource(new_source_preview_.getSource()); // reset for next time - new_source_to_create_ = ""; - texture = 0; selected_button[NAV_NEW] = false; } } - } // Hardware else { diff --git a/UserInterfaceManager.h b/UserInterfaceManager.h index 398861a..e66a647 100644 --- a/UserInterfaceManager.h +++ b/UserInterfaceManager.h @@ -13,6 +13,21 @@ using namespace std; struct ImVec2; class Source; +class SourcePreview { + + Source *source_; + std::string label_; + +public: + SourcePreview(); + + void setSource(Source *s = nullptr, std::string label = ""); + Source *getSource(); + + void draw(float width); + inline bool ready() const { return source_ != nullptr; } +}; + class Navigator { // geometry left bar @@ -34,9 +49,10 @@ class Navigator void RenderMainPannel(); int new_source_type_; - std::string new_source_to_create_; char new_source_filename_[2048]; + SourcePreview new_source_preview_; + public: Navigator();