diff --git a/CMakeLists.txt b/CMakeLists.txt index a53bf13..5c228df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -210,6 +210,7 @@ set(VMIX_SRCS View.cpp Source.cpp Session.cpp + Selection.cpp SessionSource.cpp SessionVisitor.cpp GarbageVisitor.cpp diff --git a/Decorations.cpp b/Decorations.cpp index b424c9a..cacfa83 100644 --- a/Decorations.cpp +++ b/Decorations.cpp @@ -314,7 +314,7 @@ void Icon::accept(Visitor& v) } -Selection::Selection() +Box::Box() { // color = glm::vec4( 1.f, 1.f, 1.f, 1.f); color = glm::vec4( 1.f, 0.f, 0.f, 1.f); @@ -322,7 +322,7 @@ Selection::Selection() } -void Selection::draw (glm::mat4 modelview, glm::mat4 projection) +void Box::draw (glm::mat4 modelview, glm::mat4 projection) { if ( !initialized() ) { square_->init(); diff --git a/Decorations.h b/Decorations.h index c53de82..495b64a 100644 --- a/Decorations.h +++ b/Decorations.h @@ -71,10 +71,10 @@ protected: Type type_; }; -class Selection : public Group +class Box : public Group { public: - Selection(); + Box(); void draw (glm::mat4 modelview, glm::mat4 projection) override; diff --git a/Mixer.cpp b/Mixer.cpp index e4ce30f..3394f66 100644 --- a/Mixer.cpp +++ b/Mixer.cpp @@ -326,10 +326,13 @@ void Mixer::deleteSource(Source *s) { if ( s != nullptr ) { - // in case.. + // in case it was the current source... unsetCurrentSource(); - // keep name + // in case it was selected.. + selection().remove(s); + + // keep name for log std::string name = s->name(); // remove source Nodes from all views @@ -340,6 +343,7 @@ void Mixer::deleteSource(Source *s) // delete source session_->deleteSource(s); + // log Log::Notify("Source %s deleted.", name.c_str()); } } @@ -377,16 +381,28 @@ void Mixer::setCurrentSource(SourceList::iterator it) if ( current_source_ == it ) return; + // clear current (even if it is invalid) unsetCurrentSource(); - // change current + // change current if it is valid if ( it != session_->end() ) { current_source_ = it; current_source_index_ = session_->index(it); + // add to selection + selection().add(*it); + // show status as current (*current_source_)->setMode(Source::CURRENT); } } +Source * Mixer::findSource (Node *node) +{ + SourceList::iterator it = session_->find(node); + if (it != session_->end()) + return *it; + return nullptr; +} + void Mixer::setCurrentSource(Node *node) { setCurrentSource( session_->find(node) ); @@ -423,8 +439,12 @@ void Mixer::setCurrentNext() void Mixer::unsetCurrentSource() { // discard overlay for previously current source - if ( current_source_ != session_->end() ) - (*current_source_)->setMode(Source::NORMAL); + if ( current_source_ != session_->end() ) { + // remove from selection + selection().remove( *current_source_ ); + // show status as normal + (*current_source_)->setMode(Source::NORMAL); + } // deselect current source current_source_ = session_->end(); @@ -551,6 +571,8 @@ void Mixer::swap() return; if (session_) { + // clear selection + selection().clear(); // detatch current session's nodes from views for (auto source_iter = session_->begin(); source_iter != session_->end(); source_iter++) { diff --git a/Mixer.h b/Mixer.h index bf98ceb..7738ab1 100644 --- a/Mixer.h +++ b/Mixer.h @@ -8,8 +8,7 @@ #include "View.h" #include "Session.h" -#include "Source.h" - +#include "Selection.h" class Mixer { @@ -27,6 +26,13 @@ public: return _instance; } + static Selection& selection() + { + // The only instance + static Selection _selection; + return _selection; + } + // update session and all views void update(); @@ -34,41 +40,43 @@ public: void draw(); // creation of sources - Source * createSourceFile(std::string path); - Source * createSourceClone(std::string namesource); - Source * createSourceRender(); + Source * createSourceFile (std::string path); + Source * createSourceClone (std::string namesource); + Source * createSourceRender (); // operations on sources - void addSource(Source *s); - void deleteSource(Source *s); - void renameSource(Source *s, const std::string &newname); + void addSource (Source *s); + void deleteSource (Source *s); + void renameSource (Source *s, const std::string &newname); // current source - void setCurrentSource(std::string namesource); - void setCurrentSource(Node *node); - void setCurrentSource(int index); - void setCurrentSource(Source *s); - void setCurrentNext(); - void unsetCurrentSource(); - void cloneCurrentSource(); - void deleteCurrentSource(); - Source * currentSource(); - int indexCurrentSource(); + void setCurrentSource (std::string namesource); + void setCurrentSource (Node *node); + void setCurrentSource (int index); + void setCurrentSource (Source *s); + void setCurrentNext (); + void unsetCurrentSource (); + void cloneCurrentSource (); + void deleteCurrentSource (); + int indexCurrentSource (); + + Source * currentSource (); + Source * findSource (Node *node); // management of view - View *view(View::Mode m); - void setCurrentView(View::Mode m); - View *currentView(); + View *view (View::Mode m); + void setCurrentView (View::Mode m); + View *currentView (); // manipulate, load and save sessions - inline Session *session() const { return session_; } - void clear(); - void save(); - void saveas(const std::string& filename); - void open(const std::string& filename); - void import(const std::string& filename); - void merge(Session *s); - void set(Session *s); + inline Session *session () const { return session_; } + void clear (); + void save (); + void saveas (const std::string& filename); + void open (const std::string& filename); + void import (const std::string& filename); + void merge (Session *s); + void set (Session *s); protected: diff --git a/RenderingManager.cpp b/RenderingManager.cpp index cac1559..b1e0170 100644 --- a/RenderingManager.cpp +++ b/RenderingManager.cpp @@ -674,6 +674,9 @@ void RenderingWindow::draw(FrameBuffer *fb) ShadingProgram::enduse(); glBindTexture(GL_TEXTURE_2D, 0); } + else { + Log::Info("No Framebuffer Provided to draw Rendering Window"); + } // restore attribs Rendering::manager().popAttrib(); diff --git a/Selection.cpp b/Selection.cpp new file mode 100644 index 0000000..6d612ba --- /dev/null +++ b/Selection.cpp @@ -0,0 +1,67 @@ +#include + +#include "Selection.h" + +Selection::Selection() +{ + +} + + +void Selection::add(Source *s) +{ + selection_.push_back(s); + s->setMode(Source::ACTIVE); +} + +void Selection::add(SourceList l) +{ + for(auto it = l.begin(); it != l.end(); it++) + (*it)->setMode(Source::ACTIVE); + + // generate new set as union of current selection and give list + SourceList result; + std::set_union(selection_.begin(), selection_.end(), l.begin(), l.end(), std::inserter(result, result.begin()) ); + // set new selection + selection_ = SourceList(result); +} + +void Selection::remove(Source *s) +{ + SourceList::iterator it = find(s); + if (it != selection_.end()) { + selection_.erase(it); + s->setMode(Source::NORMAL); + } +} + +void Selection::remove(SourceList l) +{ + for(auto it = l.begin(); it != l.end(); it++) + (*it)->setMode(Source::NORMAL); + + // generate new set as difference of current selection and give list + SourceList result; + std::set_difference(selection_.begin(), selection_.end(), l.begin(), l.end(), std::inserter(result, result.begin()) ); + // set new selection + selection_ = SourceList(result); +} + +void Selection::clear() +{ + for(auto it = selection_.begin(); it != selection_.end(); it++) + (*it)->setMode(Source::NORMAL); + + selection_.clear(); +} + +SourceList::iterator Selection::find(Source *s) +{ + return std::find(selection_.begin(), selection_.end(), s); +} + + +bool Selection::contains (Source *s) +{ + return (find(s) != selection_.end()); +} diff --git a/Selection.h b/Selection.h new file mode 100644 index 0000000..b6d4301 --- /dev/null +++ b/Selection.h @@ -0,0 +1,26 @@ +#ifndef SELECTION_H +#define SELECTION_H + +#include "Source.h" + +class Selection +{ + +public: + Selection(); + + void add (Source *s); + void add (SourceList l); + void remove (Source *s); + void remove (SourceList l); + void clear (); + + bool contains (Source *s); + +protected: + SourceList::iterator find (Source *s); + SourceList selection_; + +}; + +#endif // SELECTION_H diff --git a/UserInterfaceManager.cpp b/UserInterfaceManager.cpp index d55e500..0e11bfd 100644 --- a/UserInterfaceManager.cpp +++ b/UserInterfaceManager.cpp @@ -42,6 +42,7 @@ #include "ImGuiVisitor.h" #include "GstToolkit.h" #include "Mixer.h" +#include "Selection.h" #include "FrameBuffer.h" #include "MediaPlayer.h" #include "MediaSource.h" @@ -250,7 +251,7 @@ void UserInterface::handleKeyboard() } else if (ImGui::IsKeyPressed( GLFW_KEY_A )) { // select all - Mixer::manager().currentView()->selectall(); +// Mixer::manager().currentView()->selectall(); } } @@ -408,19 +409,34 @@ void UserInterface::handleMouse() // ask the view what was picked picked = Mixer::manager().currentView()->pick(point); + // if nothing picked, if ( picked.first == nullptr ) { - // nothing picked, unset current + // unset current Mixer::manager().unsetCurrentSource(); navigator.hidePannel(); - } else { - Mixer::manager().setCurrentSource( picked.first ); - if (navigator.pannelVisible()) - navigator.showPannelSource( Mixer::manager().indexCurrentSource() ); + // clear selection + Mixer::selection().clear(); + } + // something was picked + else { + // get if a source was picked + Source *s = Mixer::manager().findSource(picked.first); + + if (keyboard_modifier_active) { + // selection + Mixer::selection().add( s ); + } + // make current + else { + Mixer::manager().setCurrentSource( picked.first ); + if (navigator.pannelVisible()) + navigator.showPannelSource( Mixer::manager().indexCurrentSource() ); + } + } - // TODO deselect if current source is not in selection - Mixer::manager().currentView()->deselect(); +// Mixer::manager().currentView()->deselect(); } else if ( ImGui::IsMouseReleased(ImGuiMouseButton_Left) ) { diff --git a/View.cpp b/View.cpp index bc315e2..74c6d3a 100644 --- a/View.cpp +++ b/View.cpp @@ -30,9 +30,6 @@ bool View::need_deep_update_ = true; View::View(Mode m) : mode_(m) { - selection_ = new Selection; - selection_->visible_ = false; - scene.ws()->attach(selection_); } void View::restoreSettings() @@ -100,41 +97,28 @@ std::pair View::pick(glm::vec3 point) picked = pv.picked().back(); //DEBUG - select(glm::vec2(-1.f, -1.f), glm::vec2(1.f, 1.f)); +// select(glm::vec2(-1.f, -1.f), glm::vec2(1.f, 1.f)); } // cancel selection on clic in background else { - deselect(); +// deselect(); } return picked; } - -void View::select(glm::vec2 A, glm::vec2 B) -{ - -} - -void View::selectall() +void GeometryView::select(glm::vec2 A, glm::vec2 B) { for(auto it = scene.ws()->begin(); it != scene.ws()->end(); it++) { - if ( *it != selection_) - selection_->attach(*it); + if ( *it != selection_box_) + selection_box_->attach(*it); } - selection_->visible_ = true; + selection_box_->visible_ = true; } -void View::deselect() -{ - selection_->clear(); - selection_->visible_ = false; -} - - MixingView::MixingView() : View(MIXING) { @@ -334,6 +318,10 @@ GeometryView::GeometryView() : View(GEOMETRY) border->color = glm::vec4( COLOR_FRAME, 1.f ); scene.fg()->attach(border); + // selection box + selection_box_ = new Box; + selection_box_->visible_ = false; + scene.ws()->attach(selection_box_); } void GeometryView::update(float dt) diff --git a/View.h b/View.h index be53c16..c16bee7 100644 --- a/View.h +++ b/View.h @@ -58,9 +58,7 @@ public: return Cursor(); } // select sources provided a start and end selection points in screen coordinates - virtual void select(glm::vec2, glm::vec2); - virtual void selectall(); - virtual void deselect(); + virtual void select(glm::vec2, glm::vec2) {} virtual void restoreSettings(); virtual void saveSettings(); @@ -73,7 +71,6 @@ public: protected: Mode mode_; - class Selection *selection_; }; @@ -120,7 +117,9 @@ public: std::pair pick(glm::vec3 point) override; Cursor grab (glm::vec2 from, glm::vec2 to, Source *s, std::pair pick) override; Cursor over (glm::vec2, Source*, std::pair) override; + void select(glm::vec2, glm::vec2) override; + class Box *selection_box_; }; class LayerView : public View