diff --git a/MixingGroup.cpp b/MixingGroup.cpp index 708d810..933ec9d 100644 --- a/MixingGroup.cpp +++ b/MixingGroup.cpp @@ -2,9 +2,12 @@ #include #include +#include +#include "defines.h" #include "Source.h" #include "Decorations.h" +#include "Mixer.h" #include "Log.h" #include "MixingGroup.h" @@ -23,29 +26,145 @@ struct clockwise_centered { glm::vec2 center; }; -MixingGroup::MixingGroup (SourceList sources) : root_(nullptr), lines_(nullptr), center_(nullptr), pos_(glm::vec2(0.f, 0.f)) +MixingGroup::MixingGroup (SourceList sources) : root_(nullptr), lines_(nullptr), center_(nullptr), + center_pos_(glm::vec2(0.f, 0.f)), active_(true) { // fill the vector of sources with the given list for (auto it = sources.begin(); it != sources.end(); it++){ (*it)->mixinggroup_ = this; sources_.push_back(*it); // compute barycenter (1) - pos_ += glm::vec2((*it)->group(View::MIXING)->translation_); + center_pos_ += glm::vec2((*it)->group(View::MIXING)->translation_); } // compute barycenter (2) - pos_ /= sources_.size(); + center_pos_ /= sources_.size(); // sort the vector of sources in clockwise order around the center pos_ - std::sort(sources_.begin(), sources_.end(), clockwise_centered(pos_)); + std::sort(sources_.begin(), sources_.end(), clockwise_centered(center_pos_)); root_ = new Group; center_ = new Symbol(Symbol::CIRCLE_POINT); - center_->color = glm::vec4(0.f, 1.f, 0.f, 0.8f); - center_->translation_ = glm::vec3(pos_, 0.f); + center_->visible_ = false; + center_->color = glm::vec4(COLOR_MIXING_GROUP, 0.75f); + center_->scale_ = glm::vec3(0.6f, 0.6f, 1.f); + center_->translation_ = glm::vec3(center_pos_, 0.f); root_->attach(center_); createLineStrip(); } +MixingGroup::~MixingGroup () +{ + delete center_; + delete root_; + if (lines_) + delete lines_; +} + +void MixingGroup::update (float dt) +{ + // active if current source in the group + auto currentsource = std::find(sources_.begin(), sources_.end(), Mixer::manager().currentSource()); + setActive(currentsource != sources_.end()); + + // perform action + if (update_action_ != ACTION_NONE && updated_source_ != nullptr) { + + if (update_action_ == ACTION_GRAB_ONE ) { + + // update path + move(updated_source_); + + // compute barycenter (0) + center_pos_ = glm::vec2(0.f, 0.f); + for (auto it = sources_.begin(); it != sources_.end(); it++){ + // compute barycenter (1) + center_pos_ += glm::vec2((*it)->group(View::MIXING)->translation_); + } + // compute barycenter (2) + center_pos_ /= sources_.size(); + center_->translation_ = glm::vec3(center_pos_, 0.f); + } + else if (update_action_ == ACTION_GRAB_ALL ) { + + std::vector p = lines_->path(); + glm::vec2 displacement = glm::vec2(updated_source_->group(View::MIXING)->translation_); + displacement -= p[ index_points_[updated_source_] ]; + + // compute barycenter (0) + center_pos_ = glm::vec2(0.f, 0.f); + auto it = sources_.begin(); + for (; it != sources_.end(); it++){ + + // modify all but the already updated source + if ( *it != updated_source_ && !(*it)->locked() ) { + (*it)->group(View::MIXING)->translation_.x += displacement.x; + (*it)->group(View::MIXING)->translation_.y += displacement.y; + (*it)->touch(); + } + + // update point + p[ index_points_[*it] ] = glm::vec2((*it)->group(View::MIXING)->translation_); + + // compute barycenter (1) + center_pos_ += glm::vec2((*it)->group(View::MIXING)->translation_); + } + // compute barycenter (2) + center_pos_ /= sources_.size(); + center_->translation_ = glm::vec3(center_pos_, 0.f); + + // update path + lines_->changePath(p); + } + else if (update_action_ == ACTION_ROTATE_ALL ) { + + std::vector p = lines_->path(); + + // get angle rotation and distance scaling + glm::vec2 pos_first = glm::vec2(updated_source_->group(View::MIXING)->translation_) -center_pos_; + float angle = glm::orientedAngle( glm::normalize(pos_first), glm::vec2(1.f, 0.f) ); + float dist = glm::length( pos_first ); + glm::vec2 pos_second = glm::vec2(p[ index_points_[updated_source_] ]) -center_pos_; + angle -= glm::orientedAngle( glm::normalize(pos_second), glm::vec2(1.f, 0.f) ); + dist /= glm::length( pos_second ); + + auto it = sources_.begin(); + for (; it != sources_.end(); it++){ + + // modify all but the already updated source + if ( *it != updated_source_ && !(*it)->locked() ) { + glm::vec2 vec = glm::vec2((*it)->group(View::MIXING)->translation_) -center_pos_; + vec = glm::rotate(vec, -angle) * dist; + vec += center_pos_; + + (*it)->group(View::MIXING)->translation_.x = vec.x; + (*it)->group(View::MIXING)->translation_.y = vec.y; + (*it)->touch(); + } + + // update point + p[ index_points_[*it] ] = glm::vec2((*it)->group(View::MIXING)->translation_); + } + // update path + lines_->changePath(p); + } + + // done + updated_source_ = nullptr; + } + +} + + + +void MixingGroup::setActive (bool on) +{ + active_ = on; + + // overlays + lines_->shader()->color.a = active_ ? 0.96f : 0.5f; + center_->visible_ = update_action_ != ACTION_NONE; +} + void MixingGroup::detach (Source *s) { // find the source @@ -54,37 +173,23 @@ void MixingGroup::detach (Source *s) if (its != sources_.end()) { // erase the source from the list sources_.erase(its); - // clear index, delete lines_, and recreate path and index with remaining sources createLineStrip(); } } -void MixingGroup::update (Source *s) +void MixingGroup::move (Source *s) { // find the source std::vector::iterator its = std::find(sources_.begin(), sources_.end(), s); - + // ok, its in the list ! if (its != sources_.end() && lines_) { - - lines_->editPath(index_points_[s], glm::vec2(s->group(View::MIXING)->translation_));// -// lines_->editPath(0, glm::vec2(s->group(View::MIXING)->translation_)); - + // modify one point in the path + lines_->editPath(index_points_[s], glm::vec2(s->group(View::MIXING)->translation_)); } } -void MixingGroup::draw () -{ - -} - -//void MixingGroup::grab (glm::vec2 from, glm::vec2 to, std::pair) -//{ - -//} - - void MixingGroup::createLineStrip() { if (lines_) { @@ -102,13 +207,10 @@ void MixingGroup::createLineStrip() index_points_[*it] = path.size(); path.push_back(glm::vec2((*it)->group(View::MIXING)->translation_)); } -// // loop -// it = sources_.begin(); -// index_points_[*it] = path.size(); -// path.push_back(glm::vec2((*it)->group(View::MIXING)->translation_)); + // create - lines_ = new LineLoop(path, 2.f); - lines_->shader()->color = glm::vec4(0.f, 1.f, 0.f, 0.8f); + lines_ = new LineLoop(path, 1.5f); + lines_->shader()->color = glm::vec4(COLOR_MIXING_GROUP, 0.96f); root_->attach(lines_); } diff --git a/MixingGroup.h b/MixingGroup.h index b4c5cda..7a2d999 100644 --- a/MixingGroup.h +++ b/MixingGroup.h @@ -10,24 +10,54 @@ class Symbol; class MixingGroup { - Group *root_; - LineLoop *lines_; - Symbol *center_; - glm::vec2 pos_; - std::vector sources_; - std::map< Source *, uint> index_points_; - - void createLineStrip(); public: MixingGroup (SourceList sources); + ~MixingGroup (); - inline Node *node () { return root_; } + typedef enum { + ACTION_NONE = 0, + ACTION_GRAB_ONE = 1, + ACTION_GRAB_ALL = 2, + ACTION_ROTATE_ALL = 3 + } Action; + // actions for update + inline void setAction (Action a) { update_action_ = a; } + inline Action action () { return update_action_; } + inline void follow (Source *s) { updated_source_ = s; } + + // get node to draw + inline Group *group () { return root_; } + + // to update in Mixing View + void update (float dt); + inline bool active () const { return active_; } + void setActive (bool on); + + // individual change of a source in the group void detach (Source *s); - void update (Source *s); + void move (Source *s); + +private: + + // Drawing elements + Group *root_; + LineLoop *lines_; + Symbol *center_; + void createLineStrip(); + + // properties linked to sources + glm::vec2 center_pos_; + std::vector sources_; + std::map< Source *, uint> index_points_; + + // status and actions + bool active_; + Action update_action_; + Source *updated_source_; + - void draw (); }; #endif // MIXINGGROUP_H diff --git a/MixingView.cpp b/MixingView.cpp index f00517a..cb3a1cc 100644 --- a/MixingView.cpp +++ b/MixingView.cpp @@ -131,9 +131,11 @@ void MixingView::draw() // TODO create MixingGroup MixingGroup *mg = new MixingGroup(Mixer::selection().getCopy()); groups_.push_back(mg); - scene.fg()->attach(mg->node()); + scene.fg()->attach(mg->group()); + Source *cur = Mixer::selection().front(); + Mixer::manager().unsetCurrentSource(); Mixer::selection().clear(); - + Mixer::manager().setCurrentSource( cur ); } ImGui::Separator(); @@ -194,6 +196,10 @@ void MixingView::update(float dt) { View::update(dt); + // always update the mixinggroups + for (auto g = groups_.begin(); g != groups_.end(); g++) + (*g)->update(dt); + // a more complete update is requested // for mixing, this means restore position of the fading slider if (View::need_deep_update_ > 0) { @@ -281,8 +287,20 @@ std::pair MixingView::pick(glm::vec2 P) pick = { nullptr, glm::vec2(0.f) }; } // pick a locked source without CTRL key; cancel pick - else if ( s->locked() && !UserInterface::manager().ctrlModifier() ) + else if ( s->locked() && !UserInterface::manager().ctrlModifier() ) { pick = { nullptr, glm::vec2(0.f) }; + } + // pick on the mixing group rotation icon + else if ( pick.first == s->rotation_mixingroup_ ) { + s->mixinggroup_->setAction( MixingGroup::ACTION_ROTATE_ALL ); + } + // pick source of a mixing group + else if ( s->mixinggroup_ != nullptr ) { + if (UserInterface::manager().shiftModifier()) + s->mixinggroup_->setAction( MixingGroup::ACTION_GRAB_ONE ); + else + s->mixinggroup_->setAction( MixingGroup::ACTION_GRAB_ALL ); + } } } @@ -331,9 +349,9 @@ View::Cursor MixingView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::pai s->group(mode_)->translation_ = s->stored_status_->translation_ + gl_Position_to - gl_Position_from; // manage mixing groups - if (s->mixinggroup_ != nullptr) { - s->mixinggroup_->update(s); - + if (s->mixinggroup_ != nullptr && s->mixinggroup_->action() != MixingGroup::ACTION_NONE ) { + // indicate which source to follow + s->mixinggroup_->follow(s); } // // diagonal translation with SHIFT @@ -376,6 +394,16 @@ View::Cursor MixingView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::pai return Cursor(Cursor_ResizeAll, info.str() ); } +void MixingView::terminate() +{ + View::terminate(); + + // terminate all group actions + for (auto g = groups_.begin(); g != groups_.end(); g++) + (*g)->setAction( MixingGroup::ACTION_NONE ); + +} + void MixingView::arrow (glm::vec2 movement) { Source *s = Mixer::manager().currentSource(); diff --git a/MixingView.h b/MixingView.h index 16b829f..bee41da 100644 --- a/MixingView.h +++ b/MixingView.h @@ -18,6 +18,7 @@ public: std::pair pick(glm::vec2) override; Cursor grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair) override; + void terminate() override; void arrow (glm::vec2) override; void setAlpha (Source *s); diff --git a/Source.cpp b/Source.cpp index e60308a..7cc950f 100644 --- a/Source.cpp +++ b/Source.cpp @@ -57,6 +57,17 @@ Source::Source() : initialized_(false), symbol_(nullptr), active_(true), locked_ overlays_[View::MIXING]->attach(center); groups_[View::MIXING]->attach(overlays_[View::MIXING]); + overlay_mixinggroup_ = new Switch; + overlay_mixinggroup_->translation_.z = 0.1; + center = new Symbol(Symbol::CIRCLE_POINT, glm::vec3(0.f, 0.f, 0.1f)); + center->color = glm::vec4( COLOR_MIXING_GROUP, 0.96f); + overlay_mixinggroup_->attach(center); + rotation_mixingroup_ = new Symbol(Symbol::ROTATION, glm::vec3(0.f, 0.f, 0.1f)); + rotation_mixingroup_->color = glm::vec4( COLOR_MIXING_GROUP, 0.94f); + rotation_mixingroup_->scale_ = glm::vec3(3.f, 3.f, 1.f); + overlay_mixinggroup_->attach(rotation_mixingroup_); + groups_[View::MIXING]->attach(overlay_mixinggroup_); + // default geometry nodes groups_[View::GEOMETRY] = new Group; groups_[View::GEOMETRY]->visible_ = false; @@ -297,6 +308,9 @@ void Source::setMode(Source::Mode m) for (auto o = overlays_.begin(); o != overlays_.end(); o++) (*o).second->visible_ = current & !locked_; + overlay_mixinggroup_->visible_ = mixinggroup_!= nullptr; + overlay_mixinggroup_->setActive(current); + // show in appearance view if current groups_[View::TEXTURE]->visible_ = m > Source::VISIBLE; diff --git a/Source.h b/Source.h index 567a6e4..305ee0d 100644 --- a/Source.h +++ b/Source.h @@ -251,6 +251,8 @@ protected: // Mixing MixingGroup *mixinggroup_; + Switch *overlay_mixinggroup_; + Symbol *rotation_mixingroup_; }; diff --git a/defines.h b/defines.h index d0d54ef..35ee9fc 100644 --- a/defines.h +++ b/defines.h @@ -91,8 +91,8 @@ #define COLOR_APPEARANCE_MASK_DISABLE 0.6f, 0.6f, 0.6f #define COLOR_FRAME 0.75f, 0.2f, 0.75f #define COLOR_FRAME_LIGHT 0.9f, 0.6f, 0.9f -#define COLOR_CIRCLE 0.2f, 0.65f, 0.7f -#define COLOR_CIRCLE_LIGHT 0.6f, 0.95f, 1.f +#define COLOR_CIRCLE 0.75f, 0.2f, 0.75f +#define COLOR_MIXING_GROUP 0.f, 0.95f, 0.2f #define COLOR_LIMBO_CIRCLE 0.16f, 0.16f, 0.16f #define COLOR_SLIDER_CIRCLE 0.11f, 0.11f, 0.11f #define COLOR_STASH_CIRCLE 0.06f, 0.06f, 0.06f