mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-13 03:09:57 +01:00
Fixed and improved multi-source selection.
This commit is contained in:
69
Mixer.cpp
69
Mixer.cpp
@@ -270,7 +270,14 @@ Source * Mixer::createSourceClone(std::string namesource)
|
||||
// ready to create a source
|
||||
Source *s = nullptr;
|
||||
|
||||
SourceList::iterator origin = session_->find(namesource);
|
||||
// origin to clone is either the given name or the current
|
||||
SourceList::iterator origin = session_->end();
|
||||
if ( !namesource.empty() )
|
||||
origin =session_->find(namesource);
|
||||
else if (current_source_ != session_->end())
|
||||
origin = current_source_;
|
||||
|
||||
// have an origin, can clone it
|
||||
if (origin != session_->end()) {
|
||||
|
||||
// create a source
|
||||
@@ -285,7 +292,8 @@ Source * Mixer::createSourceClone(std::string namesource)
|
||||
|
||||
void Mixer::addSource(Source *s)
|
||||
{
|
||||
candidate_sources_.push_back(s);
|
||||
if (s != nullptr)
|
||||
candidate_sources_.push_back(s);
|
||||
}
|
||||
|
||||
void Mixer::insertSource(Source *s, bool makecurrent)
|
||||
@@ -306,22 +314,17 @@ void Mixer::insertSource(Source *s, bool makecurrent)
|
||||
layer_.scene.ws()->attach(s->group(View::LAYER));
|
||||
|
||||
if (makecurrent) {
|
||||
// set this new source as current
|
||||
setCurrentSource( sit );
|
||||
|
||||
// switch to Mixing view to show source created
|
||||
setView(View::MIXING);
|
||||
current_view_->update(0);
|
||||
current_view_->centerSource(s);
|
||||
|
||||
// set this new source as current
|
||||
setCurrentSource( sit );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Mixer::deleteCurrentSource()
|
||||
{
|
||||
deleteSource( currentSource() );
|
||||
}
|
||||
|
||||
void Mixer::deleteSource(Source *s)
|
||||
{
|
||||
if ( s != nullptr )
|
||||
@@ -387,13 +390,17 @@ void Mixer::setCurrentSource(SourceList::iterator it)
|
||||
// change current if it is valid
|
||||
if ( it != session_->end() ) {
|
||||
current_source_ = it;
|
||||
current_source_index_ = session_->index(it);
|
||||
// set selection if not already selected
|
||||
if (!selection().contains(*it))
|
||||
selection().set(*it);
|
||||
current_source_index_ = session_->index(current_source_);
|
||||
|
||||
// set selection for this only source if not already part of a selection
|
||||
if (!selection().contains(*current_source_))
|
||||
selection().set(*current_source_);
|
||||
|
||||
// show status as current
|
||||
(*current_source_)->setMode(Source::CURRENT);
|
||||
Log::Info("setCurrentSource");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Source * Mixer::findSource (Node *node)
|
||||
@@ -404,6 +411,14 @@ Source * Mixer::findSource (Node *node)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Source * Mixer::findSource (std::string namesource)
|
||||
{
|
||||
SourceList::iterator it = session_->find(namesource);
|
||||
if (it != session_->end())
|
||||
return *it;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Mixer::setCurrentSource(Node *node)
|
||||
{
|
||||
setCurrentSource( session_->find(node) );
|
||||
@@ -439,18 +454,20 @@ void Mixer::setCurrentNext()
|
||||
|
||||
void Mixer::unsetCurrentSource()
|
||||
{
|
||||
Log::Info("unsetCurrentSource");
|
||||
|
||||
// discard overlay for previously current source
|
||||
if ( current_source_ != session_->end() ) {
|
||||
// if (selection().size() > 1) {
|
||||
|
||||
// }
|
||||
// // current source is the sole selected source : unselect and
|
||||
// else
|
||||
// current source is part of a selection, just change status
|
||||
if (selection().size() > 1) {
|
||||
(*current_source_)->setMode(Source::SELECTED);
|
||||
}
|
||||
// current source is the only selected source, unselect too
|
||||
else
|
||||
{
|
||||
// remove from selection
|
||||
// selection().remove( *current_source_ );
|
||||
// show status as normal
|
||||
(*current_source_)->setMode(Source::SELECTED);
|
||||
selection().remove( *current_source_ );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,16 +476,6 @@ 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_;
|
||||
|
||||
22
Mixer.h
22
Mixer.h
@@ -41,7 +41,7 @@ public:
|
||||
|
||||
// creation of sources
|
||||
Source * createSourceFile (std::string path);
|
||||
Source * createSourceClone (std::string namesource);
|
||||
Source * createSourceClone (std::string namesource = "");
|
||||
Source * createSourceRender ();
|
||||
|
||||
// operations on sources
|
||||
@@ -50,34 +50,32 @@ public:
|
||||
void renameSource (Source *s, const std::string &newname);
|
||||
|
||||
// current source
|
||||
void setCurrentSource (Source *s);
|
||||
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 ();
|
||||
|
||||
// browsing into sources
|
||||
Source * findSource (Node *node);
|
||||
Source * findSource (std::string name);
|
||||
|
||||
// management of view
|
||||
View *view (View::Mode m = View::INVALID);
|
||||
View *view (View::Mode m = View::INVALID);
|
||||
void setView (View::Mode m);
|
||||
// View *currentView ();
|
||||
|
||||
// manipulate, load and save sessions
|
||||
inline Session *session () const { return session_; }
|
||||
void clear ();
|
||||
void save ();
|
||||
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);
|
||||
void merge (Session *s);
|
||||
void set (Session *s);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -4,18 +4,25 @@
|
||||
|
||||
Selection::Selection()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Selection::add(Source *s)
|
||||
{
|
||||
if (s == nullptr)
|
||||
return;
|
||||
|
||||
selection_.push_back(s);
|
||||
selection_.sort();
|
||||
selection_.unique();
|
||||
s->setMode(Source::SELECTED);
|
||||
}
|
||||
|
||||
void Selection::remove(Source *s)
|
||||
{
|
||||
if (s == nullptr)
|
||||
return;
|
||||
|
||||
SourceList::iterator it = find(s);
|
||||
if (it != selection_.end()) {
|
||||
selection_.erase(it);
|
||||
@@ -25,6 +32,9 @@ void Selection::remove(Source *s)
|
||||
|
||||
void Selection::toggle(Source *s)
|
||||
{
|
||||
if (s == nullptr)
|
||||
return;
|
||||
|
||||
if (contains(s))
|
||||
remove(s);
|
||||
else
|
||||
@@ -34,6 +44,10 @@ void Selection::toggle(Source *s)
|
||||
void Selection::set(Source *s)
|
||||
{
|
||||
clear();
|
||||
|
||||
if (s == nullptr)
|
||||
return;
|
||||
|
||||
selection_.push_back(s);
|
||||
s->setMode(Source::SELECTED);
|
||||
}
|
||||
@@ -91,6 +105,16 @@ uint Selection::size()
|
||||
return selection_.size();
|
||||
}
|
||||
|
||||
Source *Selection::front()
|
||||
{
|
||||
return selection_.front();
|
||||
}
|
||||
|
||||
bool Selection::empty()
|
||||
{
|
||||
return selection_.empty();
|
||||
}
|
||||
|
||||
SourceList::iterator Selection::find(Source *s)
|
||||
{
|
||||
return std::find(selection_.begin(), selection_.end(), s);
|
||||
@@ -111,3 +135,5 @@ SourceList::iterator Selection::end()
|
||||
{
|
||||
return selection_.end();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -21,13 +21,14 @@ public:
|
||||
|
||||
SourceList::iterator begin ();
|
||||
SourceList::iterator end ();
|
||||
Source *front();
|
||||
bool contains (Source *s);
|
||||
bool empty();
|
||||
uint size ();
|
||||
|
||||
protected:
|
||||
SourceList::iterator find (Source *s);
|
||||
SourceList selection_;
|
||||
|
||||
};
|
||||
|
||||
#endif // SELECTION_H
|
||||
|
||||
@@ -180,6 +180,7 @@ void Source::setMode(Source::Mode m)
|
||||
|
||||
}
|
||||
|
||||
// test update callback
|
||||
void fix_ar(Node *n)
|
||||
{
|
||||
n->scale_.y = n->scale_.x;
|
||||
@@ -222,7 +223,9 @@ void Source::attach(FrameBuffer *renderbuffer)
|
||||
// test update callback
|
||||
// groups_[View::GEOMETRY]->update_callbacks_.push_front(fix_ar);
|
||||
|
||||
setMode(Source::NORMAL);
|
||||
// make the source visible
|
||||
if ( mode_ == HIDDEN )
|
||||
setMode(NORMAL);
|
||||
}
|
||||
|
||||
void Source::update(float dt)
|
||||
|
||||
@@ -274,7 +274,7 @@ void UserInterface::handleKeyboard()
|
||||
else if ( !ImGui::IsAnyWindowFocused() ){
|
||||
// Backspace to delete source
|
||||
if (ImGui::IsKeyPressed( GLFW_KEY_BACKSPACE ) || ImGui::IsKeyPressed( GLFW_KEY_DELETE ))
|
||||
Mixer::manager().deleteCurrentSource();
|
||||
Mixer::manager().deleteSource( Mixer::manager().currentSource() );
|
||||
// button esc to toggle fullscreen
|
||||
else if (ImGui::IsKeyPressed( GLFW_KEY_ESCAPE ))
|
||||
Rendering::manager().mainWindow().setFullscreen(nullptr);
|
||||
@@ -293,17 +293,16 @@ void UserInterface::handleKeyboard()
|
||||
}
|
||||
|
||||
|
||||
void setMouseCursor(View::Cursor c = View::Cursor())
|
||||
void setMouseCursor(glm::vec2 mousepos, View::Cursor c = View::Cursor())
|
||||
{
|
||||
ImGui::SetMouseCursor(c.type);
|
||||
|
||||
if ( !c.info.empty()) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
float d = 0.5f * ImGui::GetFrameHeight() ;
|
||||
ImVec2 window_pos = ImVec2( io.MousePos.x - d, io.MousePos.y - d );
|
||||
ImVec2 window_pos = ImVec2( mousepos.x - d, mousepos.y - d );
|
||||
ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always);
|
||||
ImGui::SetNextWindowBgAlpha(0.75f); // Transparent background
|
||||
if (ImGui::Begin("MouseInfoContext", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav))
|
||||
if (ImGui::Begin("MouseInfoContext", NULL, ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav))
|
||||
{
|
||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_MONO);
|
||||
ImGui::Text(" %s", c.info.c_str());
|
||||
@@ -322,6 +321,7 @@ void UserInterface::handleMouse()
|
||||
mouseclic[ImGuiMouseButton_Left] = glm::vec2(io.MouseClickedPos[ImGuiMouseButton_Left].x * io.DisplayFramebufferScale.y, io.MouseClickedPos[ImGuiMouseButton_Left].y* io.DisplayFramebufferScale.x);
|
||||
mouseclic[ImGuiMouseButton_Right] = glm::vec2(io.MouseClickedPos[ImGuiMouseButton_Right].x * io.DisplayFramebufferScale.y, io.MouseClickedPos[ImGuiMouseButton_Right].y* io.DisplayFramebufferScale.x);
|
||||
|
||||
static bool mousedown = false;
|
||||
static std::pair<Node *, glm::vec2> picked = { nullptr, glm::vec2(0.f) };
|
||||
|
||||
// steal focus on right button clic
|
||||
@@ -332,7 +332,6 @@ void UserInterface::handleMouse()
|
||||
// if not on any window
|
||||
if ( !ImGui::IsAnyWindowHovered() && !ImGui::IsAnyWindowFocused() )
|
||||
{
|
||||
Source *current = Mixer::manager().currentSource();
|
||||
|
||||
// if (current)
|
||||
// {
|
||||
@@ -361,13 +360,12 @@ void UserInterface::handleMouse()
|
||||
{
|
||||
// right mouse drag => drag current view
|
||||
View::Cursor c = Mixer::manager().view()->drag( mouseclic[ImGuiMouseButton_Right], mousepos);
|
||||
setMouseCursor(c);
|
||||
setMouseCursor(mousepos, c);
|
||||
}
|
||||
else if ( ImGui::IsMouseDown(ImGuiMouseButton_Right)) {
|
||||
|
||||
Mixer::manager().unsetCurrentSource();
|
||||
navigator.hidePannel();
|
||||
|
||||
// glm::vec3 point = Rendering::manager().unProject(mousepos, Mixer::manager().currentView()->scene.root()->transform_ );
|
||||
|
||||
}
|
||||
@@ -379,74 +377,60 @@ void UserInterface::handleMouse()
|
||||
//
|
||||
// LEFT Mouse button
|
||||
//
|
||||
if ( ImGui::IsMouseDragging(ImGuiMouseButton_Left, 5.0f) )
|
||||
{
|
||||
if (current)
|
||||
if ( ImGui::IsMouseDown(ImGuiMouseButton_Left) ) {
|
||||
|
||||
if ( !mousedown)
|
||||
{
|
||||
mousedown = true;
|
||||
Log::Info("LMB %d", mousedown);
|
||||
|
||||
// grab current source
|
||||
// View::Cursor c = Mixer::manager().currentView()->grab(current, mouseclic[ImGuiMouseButton_Left], mousepos, picked);
|
||||
// setMouseCursor(c);
|
||||
// grab selected sources (current is also selected by default)
|
||||
View::Cursor c = View::Cursor_Arrow;
|
||||
for (auto it = Mixer::selection().begin(); it != Mixer::selection().end(); it++)
|
||||
c = Mixer::manager().view()->grab(*it, mouseclic[ImGuiMouseButton_Left], mousepos, picked);
|
||||
setMouseCursor(c);
|
||||
}
|
||||
else {
|
||||
// Selection area
|
||||
ImGui::GetBackgroundDrawList()->AddRect(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
|
||||
ImGui::GetColorU32(ImGuiCol_ResizeGripHovered));
|
||||
ImGui::GetBackgroundDrawList()->AddRectFilled(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
|
||||
ImGui::GetColorU32(ImGuiCol_ResizeGripHovered, 0.3f));
|
||||
// ask the view what was picked
|
||||
picked = Mixer::manager().view()->pick(mousepos);
|
||||
|
||||
// Bounding box multiple sources selection
|
||||
Mixer::manager().view()->select(mouseclic[ImGuiMouseButton_Left], mousepos);
|
||||
|
||||
}
|
||||
}
|
||||
else if ( ImGui::IsMouseClicked(ImGuiMouseButton_Left) ) {
|
||||
|
||||
// ask the view what was picked
|
||||
picked = Mixer::manager().view()->pick(mousepos);
|
||||
|
||||
// if nothing picked,
|
||||
if ( picked.first == nullptr ) {
|
||||
// unset current
|
||||
Mixer::manager().unsetCurrentSource();
|
||||
navigator.hidePannel();
|
||||
// clear selection
|
||||
Mixer::selection().clear();
|
||||
}
|
||||
// something was picked
|
||||
else {
|
||||
// get if a source was picked
|
||||
Source *s = Mixer::manager().findSource(picked.first);
|
||||
if (s != nullptr) {
|
||||
|
||||
if (keyboard_modifier_active) {
|
||||
// selection
|
||||
Mixer::selection().toggle( s ); // TODO toggle selection
|
||||
}
|
||||
// make current
|
||||
else {
|
||||
Mixer::manager().setCurrentSource( s );
|
||||
if (navigator.pannelVisible())
|
||||
navigator.showPannelSource( Mixer::manager().indexCurrentSource() );
|
||||
}
|
||||
|
||||
// indicate to view that an action can be initiated (e.g. grab)
|
||||
Mixer::manager().view()->initiate();
|
||||
// if nothing picked,
|
||||
if ( picked.first == nullptr ) {
|
||||
// unset current
|
||||
Mixer::manager().unsetCurrentSource();
|
||||
navigator.hidePannel();
|
||||
// clear selection
|
||||
Mixer::selection().clear();
|
||||
}
|
||||
// something was picked
|
||||
else {
|
||||
// get if a source was picked
|
||||
Source *s = Mixer::manager().findSource(picked.first);
|
||||
if (s != nullptr) {
|
||||
|
||||
if (keyboard_modifier_active) {
|
||||
if ( !Mixer::selection().contains(s) )
|
||||
Mixer::selection().add( s );
|
||||
else {
|
||||
Mixer::selection().remove( s );
|
||||
if ( Mixer::selection().size() > 1 )
|
||||
s = Mixer::selection().front();
|
||||
else {
|
||||
s = nullptr;
|
||||
}
|
||||
}
|
||||
// Mixer::selection().toggle( Mixer::manager().currentSource() );
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
Mixer::manager().setCurrentSource( s );
|
||||
if (navigator.pannelVisible())
|
||||
navigator.showPannelSource( Mixer::manager().indexCurrentSource() );
|
||||
|
||||
}
|
||||
|
||||
// indicate to view that an action can be initiated (e.g. grab)
|
||||
Mixer::manager().view()->initiate();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( ImGui::IsMouseReleased(ImGuiMouseButton_Left) )
|
||||
{
|
||||
picked = { nullptr, glm::vec2(0.f) };
|
||||
|
||||
}
|
||||
if ( ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) )
|
||||
else if ( ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) )
|
||||
{
|
||||
// display source in left pannel
|
||||
navigator.showPannelSource( Mixer::manager().indexCurrentSource() );
|
||||
@@ -454,7 +438,39 @@ void UserInterface::handleMouse()
|
||||
// (because single clic maintains same source active)
|
||||
Mixer::manager().unsetCurrentSource();
|
||||
}
|
||||
else if ( ImGui::IsMouseReleased(ImGuiMouseButton_Left) )
|
||||
{
|
||||
mousedown = false;
|
||||
Log::Info("LMB %d", mousedown);
|
||||
|
||||
picked = { nullptr, glm::vec2(0.f) };
|
||||
}
|
||||
|
||||
// if ( mousedown && glm::distance(mouseclic[ImGuiMouseButton_Left], mousepos) > 3.f )
|
||||
if ( ImGui::IsMouseDragging(ImGuiMouseButton_Left, 5.0f) )
|
||||
{
|
||||
// Log::Info("LMB drag %f", glm::distance(mouseclic[ImGuiMouseButton_Left], mousepos));
|
||||
|
||||
Source *current = Mixer::manager().currentSource();
|
||||
if (current)
|
||||
{
|
||||
// grab selected sources (current is also selected by default)
|
||||
View::Cursor c = View::Cursor_Arrow;
|
||||
for (auto it = Mixer::selection().begin(); it != Mixer::selection().end(); it++)
|
||||
c = Mixer::manager().view()->grab(*it, mouseclic[ImGuiMouseButton_Left], mousepos, picked);
|
||||
setMouseCursor(mousepos, c);
|
||||
}
|
||||
else {
|
||||
// Selection area
|
||||
ImGui::GetBackgroundDrawList()->AddRect(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
|
||||
ImGui::GetColorU32(ImGuiCol_ResizeGripHovered));
|
||||
ImGui::GetBackgroundDrawList()->AddRectFilled(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
|
||||
ImGui::GetColorU32(ImGuiCol_ResizeGripHovered, 0.3f));
|
||||
|
||||
// Bounding box multiple sources selection
|
||||
Mixer::manager().view()->select(mouseclic[ImGuiMouseButton_Left], mousepos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1198,7 +1214,7 @@ void Navigator::RenderSourcePannel(Source *s)
|
||||
ImGui::Text(" ");
|
||||
// Action on source
|
||||
if ( ImGui::Button( ICON_FA_SHARE_SQUARE " Clone", ImVec2(ImGui::GetContentRegionAvail().x, 0)) )
|
||||
Mixer::manager().cloneCurrentSource();
|
||||
Mixer::manager().addSource ( Mixer::manager().createSourceClone() );
|
||||
if ( ImGui::Button( ICON_FA_BACKSPACE " Delete", ImVec2(ImGui::GetContentRegionAvail().x, 0)) ) {
|
||||
Mixer::manager().deleteSource(s);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user