diff --git a/ControlManager.cpp b/ControlManager.cpp index 4583b4b..6f7a5e5 100644 --- a/ControlManager.cpp +++ b/ControlManager.cpp @@ -834,7 +834,7 @@ void Control::sendSourcesStatus(const IpEndpointName &remoteEndpoint, osc::Recei int i = 0; char oscaddr[128]; int index_current = Mixer::manager().indexCurrentSource(); - for (; i < Mixer::manager().count(); ++i) { + for (; i < Mixer::manager().numSource(); ++i) { // send status of currently selected sprintf(oscaddr, OSC_PREFIX OSC_CURRENT "/%d", i); p << osc::BeginMessage( oscaddr ) << (index_current == i ? 1.f : 0.f) << osc::EndMessage; diff --git a/LayerView.cpp b/LayerView.cpp index 6b591a5..45cfb79 100644 --- a/LayerView.cpp +++ b/LayerView.cpp @@ -121,7 +121,7 @@ void LayerView::draw() // special action of Mixing view if (candidate_flatten_group){ if (ImGui::Selectable( ICON_FA_DOWNLOAD " Flatten" )) { - Mixer::manager().groupSelection(); + Mixer::manager().flattenSelection(); } } else { diff --git a/Mixer.cpp b/Mixer.cpp index 8359a59..64def71 100644 --- a/Mixer.cpp +++ b/Mixer.cpp @@ -627,20 +627,10 @@ void Mixer::uncover(Source *s) } } - -void Mixer::deselect(Source *s) -{ - if ( s != nullptr ) { - if ( s == *current_source_) - unsetCurrentSource(); - Mixer::selection().remove(s); - } -} - void Mixer::deleteSelection() { // number of sources in selection - int N = selection().size(); + uint N = selection().size(); // ignore if selection empty if (N > 0) { @@ -671,7 +661,7 @@ void Mixer::deleteSelection() } } -void Mixer::groupSelection() +void Mixer::flattenSelection() { if (selection().empty()) return; @@ -729,6 +719,38 @@ void Mixer::groupSelection() Mixer::manager().setCurrentSource(sessiongroup); } +void Mixer::flatten() +{ + // + SessionGroupSource *sessiongroup = new SessionGroupSource; + sessiongroup->setSession(session_); + + // set alpha to full opacity + sessiongroup->group(View::MIXING)->translation_.x = 0.f; + sessiongroup->group(View::MIXING)->translation_.y = 0.f; + + // propose a name to the session group + sessiongroup->setName( SystemToolkit::base_filename(session_->filename())); + + // create a session containing the sessiongroup + Session *futuresession = new Session; + futuresession->addSource( sessiongroup ); + + // set and swap to futuresession + set(futuresession); + + // detatch current session's nodes from views + for (auto source_iter = session_->begin(); source_iter != session_->end(); source_iter++) + detach(*source_iter); + // detatch session's mixing group + for (auto group_iter = session_->beginMixingGroup(); group_iter != session_->endMixingGroup(); group_iter++) + (*group_iter)->attachTo(nullptr); + // prevent deletion of session_ (now embedded into session group) + session_ = new Session; + + Log::Notify("Created source '%s' with %s", sessiongroup->name().c_str(), sessiongroup->info().c_str()); +} + void Mixer::renameSource(Source *s, const std::string &newname) { if ( s != nullptr ) @@ -932,7 +954,7 @@ int Mixer::indexCurrentSource() const return current_source_index_; } -int Mixer::count() const +int Mixer::numSource() const { return (int) session_->numSource(); } @@ -982,9 +1004,13 @@ void Mixer::setView(View::Mode m) Settings::application.current_view = (int) m; // selection might have to change - for (auto sit = session_->begin(); sit != session_->end(); sit++) { - if ( !current_view_->canSelect(*sit) ) - deselect( *sit ); + for (auto sit = session_->begin(); sit != session_->end(); ++sit) { + Source *s = *sit; + if ( s != nullptr && !current_view_->canSelect( s ) ) { + if ( s == *current_source_ ) + unsetCurrentSource(); + Mixer::selection().remove( s ); + } } // need to deeply update view to apply eventual changes @@ -1235,7 +1261,7 @@ void Mixer::merge(SessionSource *source) void Mixer::swap() { - if (!back_session_ || !session_) + if (!back_session_) return; if (session_) { @@ -1244,6 +1270,9 @@ void Mixer::swap() // detatch current session's nodes from views for (auto source_iter = session_->begin(); source_iter != session_->end(); source_iter++) detach(*source_iter); + // detatch session's mixing group + for (auto group_iter = session_->beginMixingGroup(); group_iter != session_->endMixingGroup(); group_iter++) + (*group_iter)->attachTo(nullptr); } // swap back and front @@ -1268,16 +1297,18 @@ void Mixer::swap() // set resolution session_->setResolution( session_->config(View::RENDERING)->scale_ ); - // transfer fading - session_->setFadingTarget( MAX(back_session_->fadingTarget(), session_->fadingTarget())); - // no current source current_source_ = session_->end(); current_source_index_ = -1; - // delete back (former front session) - garbage_.push_back(back_session_); - back_session_ = nullptr; + if (back_session_) { + // transfer fading + session_->setFadingTarget( MAX(back_session_->fadingTarget(), session_->fadingTarget())); + + // delete back (former front session) + garbage_.push_back(back_session_); + back_session_ = nullptr; + } // reset History manager Action::manager().init(); @@ -1338,6 +1369,8 @@ void Mixer::set(Session *s) sessionSwapRequested_ = true; } + + void Mixer::setResolution(glm::vec3 res) { if (session_) { diff --git a/Mixer.h b/Mixer.h index 0867c3d..a0ea8f7 100644 --- a/Mixer.h +++ b/Mixer.h @@ -39,12 +39,12 @@ public: } // update session and all views - void update(); - inline float dt() const { return dt_;} // in miliseconds - inline int fps() const { return int(roundf(1000.f/dt__));} + void update (); + inline float dt () const { return dt_; } // in miliseconds + inline int fps () const { return int(roundf(1000.f/dt__)); } // draw session and current view - void draw(); + void draw (); // creation of sources Source * createSourceFile (const std::string &path); @@ -62,37 +62,37 @@ public: void addSource (Source *s); void deleteSource (Source *s); void renameSource (Source *s, const std::string &newname = ""); - void attach (Source *s); - void detach (Source *s); - void deselect (Source *s); - void deleteSelection(); - void groupSelection(); + int numSource () const; + + // operations on selection + void deleteSelection (); + void flattenSelection (); // current source - Source * currentSource (); + Source *currentSource (); void setCurrentSource (Source *s); void setCurrentSource (std::string namesource); void setCurrentSource (Node *node); void setCurrentSource (uint64_t id); - void setCurrentNext (); + void setCurrentNext (); void setCurrentPrevious (); void unsetCurrentSource (); + // access though indices Source *sourceAtIndex (int index); - void setCurrentIndex (int index); - void moveIndex (int current_index, int target_index); + void setCurrentIndex (int index); + void moveIndex (int current_index, int target_index); int indexCurrentSource () const; - int count() const; // browsing into sources - Source * findSource (Node *node); - Source * findSource (std::string name); - Source * findSource (uint64_t id); + Source * findSource (Node *node); + Source * findSource (std::string name); + Source * findSource (uint64_t id); SourceList findSources (float depth_from, float depth_to); - SourceList validate(const SourceList &list); + SourceList validate (const SourceList &list); // management of view - View *view (View::Mode m = View::INVALID); + View * view (View::Mode m = View::INVALID); void setView (View::Mode m); void conceal (Source *s); @@ -100,7 +100,7 @@ public: bool concealed(Source *s); // manipulate, load and save sessions - inline Session *session () const { return session_; } + inline Session * session () const { return session_; } void clear (); void save (bool with_version = false); void saveas (const std::string& filename, bool with_version = false); @@ -113,6 +113,8 @@ public: void setResolution(glm::vec3 res); bool busy () const { return busy_; } + void flatten(); + // operations depending on transition mode void close (bool smooth = false); void open (const std::string& filename, bool smooth = false); @@ -136,6 +138,8 @@ protected: void insertSource (Source *s, View::Mode m = View::INVALID); bool replaceSource (Source *from, Source *to); bool recreateSource(Source *s); + void attach (Source *s); + void detach (Source *s); void setCurrentSource(SourceList::iterator it); SourceList::iterator current_source_; diff --git a/Session.cpp b/Session.cpp index 80a8254..baf2952 100644 --- a/Session.cpp +++ b/Session.cpp @@ -255,13 +255,13 @@ SourceList::iterator Session::addSource(Source *s) // find the source SourceList::iterator its = find(s); - // ok, its NOT in the list ! + // ok, it's NOT in the list ! if (its == sources_.end()) { // insert the source in the rendering render_.scene.ws()->attach(s->group(View::RENDERING)); - // insert the source to the beginning of the list + // insert the source to the end of the list sources_.push_back(s); - // return the iterator to the source created at the beginning + // return the iterator to the source created at the end its = --sources_.end(); } diff --git a/SessionSource.cpp b/SessionSource.cpp index 1331dc0..c773c25 100644 --- a/SessionSource.cpp +++ b/SessionSource.cpp @@ -350,6 +350,16 @@ void SessionGroupSource::init() } } +void SessionGroupSource::setSession (Session *s) +{ + if (s) { + if ( session_ ) + delete session_; + session_ = s; + resolution_ = s->frame()->resolution(); + } +} + bool SessionGroupSource::import(Source *source) { bool ret = false; diff --git a/SessionSource.h b/SessionSource.h index c74d8a8..0f01b01 100644 --- a/SessionSource.h +++ b/SessionSource.h @@ -69,6 +69,7 @@ public: void accept (Visitor& v) override; // SessionGroup Source specific interface + void setSession (Session *s); inline void setResolution (glm::vec3 v) { resolution_ = v; } // import a source diff --git a/UserInterfaceManager.cpp b/UserInterfaceManager.cpp index 3952fde..36ac233 100644 --- a/UserInterfaceManager.cpp +++ b/UserInterfaceManager.cpp @@ -924,6 +924,7 @@ void UserInterface::showMenuEdit() void UserInterface::showMenuFile() { + // NEW if (ImGui::MenuItem( MENU_NEW_FILE, SHORTCUT_NEW_FILE)) { Mixer::manager().close(); navigator.hidePannel(); @@ -933,21 +934,27 @@ void UserInterface::showMenuFile() ImGui::SetNextItemWidth( ImGui::GetContentRegionAvail().x * 0.54f); ImGui::Combo("Height", &Settings::application.render.res, FrameBuffer::resolution_name, IM_ARRAYSIZE(FrameBuffer::resolution_name) ); - ImGui::Separator(); + if (ImGui::MenuItem( ICON_FA_FILE_IMPORT " Embed in New file", nullptr, false, Mixer::manager().numSource() > 0)) { + Mixer::manager().flatten(); + } - ImGui::MenuItem( ICON_FA_LEVEL_UP_ALT " Open last on start", nullptr, &Settings::application.recentSessions.load_at_start); + // FILE OPEN AND SAVE + ImGui::Separator(); + const std::string currentfilename = Mixer::manager().session()->filename(); + const bool currentfileopen = !currentfilename.empty(); + + ImGui::MenuItem( MENU_OPEN_ON_START, nullptr, &Settings::application.recentSessions.load_at_start); if (ImGui::MenuItem( MENU_OPEN_FILE, SHORTCUT_OPEN_FILE)) selectOpenFilename(); - if (ImGui::MenuItem( MENU_REOPEN_FILE, SHORTCUT_REOPEN_FILE)) - Mixer::manager().load( Mixer::manager().session()->filename() ); - - if (ImGui::MenuItem( ICON_FA_FILE_EXPORT " Import") && sessionimportdialog) { + if (ImGui::MenuItem( MENU_REOPEN_FILE, SHORTCUT_REOPEN_FILE, false, currentfileopen)) + Mixer::manager().load( currentfilename ); + if (sessionimportdialog && ImGui::MenuItem( ICON_FA_FILE_EXPORT " Import sources" )) { // launch file dialog to open a session file sessionimportdialog->open(); navigator.hidePannel(); } - if (ImGui::MenuItem( MENU_SAVE_FILE, SHORTCUT_SAVE_FILE)) { + if (ImGui::MenuItem( MENU_SAVE_FILE, SHORTCUT_SAVE_FILE, false, currentfileopen)) { if (saveOrSaveAs()) navigator.hidePannel(); } @@ -956,6 +963,7 @@ void UserInterface::showMenuFile() ImGui::MenuItem( MENU_SAVE_ON_EXIT, nullptr, &Settings::application.recentSessions.save_on_exit); + // HELP AND QUIT ImGui::Separator(); if (ImGui::MenuItem( IMGUI_TITLE_HELP, SHORTCUT_HELP)) Settings::application.widget.help = true; diff --git a/UserInterfaceManager.h b/UserInterfaceManager.h index 61b482a..602b41b 100644 --- a/UserInterfaceManager.h +++ b/UserInterfaceManager.h @@ -39,10 +39,11 @@ #define SHORTCUT_SAVE_FILE CTRL_MOD "S" #define MENU_SAVEAS_FILE ICON_FA_FILE_DOWNLOAD " Save as" #define MENU_SAVE_ON_EXIT ICON_FA_LEVEL_DOWN_ALT " Save on exit" +#define MENU_OPEN_ON_START ICON_FA_LEVEL_UP_ALT " Open last on start" #define SHORTCUT_SAVEAS_FILE CTRL_MOD "Shift+S" #define SHORTCUT_HELP CTRL_MOD "H" #define SHORTCUT_LOGS CTRL_MOD "L" -#define MENU_QUIT ICON_FA_POWER_OFF " Quit" +#define MENU_QUIT ICON_FA_POWER_OFF " Quit" #define SHORTCUT_QUIT CTRL_MOD "Q" #define MENU_CUT ICON_FA_CUT " Cut" #define SHORTCUT_CUT CTRL_MOD "X"